⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
			}
		else
			status = readUniversal( stream );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

/* Read an RTCS request/response */

static int readRtcsRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
	int length, endPos, status;

	/* Read the outer wrapper and SEQUENCE OF request info and make the 
	   currently selected one the start of the list */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	status = readSequence( stream, &length );
	while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
		{
		const int innerStartPos = stell( stream );

		status = readRtcsRequestEntry( stream, &certValInfo->validityInfo, 
									   certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusError( status ) )
		/* The invalid attribute isn't quite a user certificate, but it's the
		   data that arose from a user certificate so it's the most 
		   appropriate locus for the error */
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
								 status ) );
	certValInfo->currentValidity = certValInfo->validityInfo;

	/* Read the extensions if there are any present.  Because some requests 
	   will have broken encoding of lengths, we allow for a bit of slop for
	   software that gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_RTCS_REQUEST, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

static int readRtcsResponseInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	CERT_VAL_INFO *certValInfo = certInfoPtr->cCertVal;
	int length, endPos, status;

	/* Read the SEQUENCE OF validity info and make the currently selected 
	   one the start of the list */
	status = readSequence( stream, &length );
	endPos = stell( stream ) + length;
	while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
		{
		const int innerStartPos = stell( stream );

		status = readRtcsResponseEntry( stream, &certValInfo->validityInfo, 
										certInfoPtr, FALSE );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusError( status ) )
		/* The invalid attribute isn't quite a user certificate, but it's the
		   data that arose from a user certificate so it's the most 
		   appropriate locus for the error */
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
								 status ) );
	certValInfo->currentValidity = certValInfo->validityInfo;
	if( stell( stream ) > endPos - MIN_ATTRIBUTE_SIZE )
		return( CRYPT_OK );

	/* Read the extensions */
	return( readAttributes( stream, &certInfoPtr->attributes,
					CRYPT_CERTTYPE_RTCS_RESPONSE, endPos - stell( stream ),
					&certInfoPtr->errorLocus, &certInfoPtr->errorType ) );
	}

/* Read an OCSP request/response */

static int readOcspRequestInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	int length, endPos, status;

	/* Read the wrapper, version information, and requestor name */
	readSequence( stream, &length );
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_OR_VERSION ) )
		{
		long version;

		readConstructed( stream, NULL, CTAG_OR_VERSION );
		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( status );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	else
		certInfoPtr->version = 1;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_OR_DUMMY ) )
		readUniversal( stream );

	/* Read the SEQUENCE OF revocation info and make the currently selected 
	   one the start of the list */
	status = readSequence( stream, &length );
	while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
		{
		const int innerStartPos = stell( stream );

		status = readOcspRequestEntry( stream, &certRevInfo->revocations, 
									   certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusError( status ) )
		/* The invalid attribute isn't quite a user certificate, but it's the
		   data that arose from a user certificate so it's the most 
		   appropriate locus for the error */
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
								 status ) );
	certRevInfo->currentRevocation = certRevInfo->revocations;

	/* Read the extensions if there are any present.  Because some requests 
	   will have broken encoding of lengths, we allow for a bit of slop for
	   software that gets the length encoding wrong by a few bytes */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_OCSP_REQUEST, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Fix up any problems in attributes */
	return( fixAttributes( certInfoPtr ) );
	}

static int readOcspResponseInfo( STREAM *stream, CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	int length, endPos, status;

	/* Read the wrapper, version information, and responder ID */
	certInfoPtr->version = 1;
	readSequence( stream, &length );			/* tbsResponseData */
	endPos = stell( stream ) + length;
	if( peekTag( stream ) == MAKE_CTAG( CTAG_OP_VERSION ) )
		{
		long version;

		readConstructed( stream, NULL, CTAG_OP_VERSION );
		status = readShortInteger( stream, &version );
		if( cryptStatusError( status ) )
			return( status );
		certInfoPtr->version = version + 1;	/* Zero-based */
		}
	if( peekTag( stream ) == MAKE_CTAG( 1 ) )
		{
		/* It's a DN, read it as the issuer name in case the caller is 
		   interested in it */
		readConstructed( stream, NULL, 1 );
		status = readIssuerDN( stream, certInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		/* We can't do much with a key hash, in any case all current 
		   responders use the issuer DN to identify the responder so
		   this shouldn't be much of a problem */
		readUniversal( stream );
	readGeneralizedTime( stream, NULL );		/* producedAt */

	/* Read the SEQUENCE OF revocation info and make the currently selected 
	   one the start of the list */
	status = readSequence( stream, &length );
	while( cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE )
		{
		const int innerStartPos = stell( stream );

		status = readOcspResponseEntry( stream, &certRevInfo->revocations, 
										certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusError( status ) )
		/* The invalid attribute isn't quite a user certificate, but it's the
		   data that arose from a user certificate so it's the most 
		   appropriate locus for the error */
		return( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_CERTIFICATE,
								 status ) );
	certRevInfo->currentRevocation = certRevInfo->revocations;

	/* Read the extensions if there are any present */
	if( stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		status = readAttributes( stream, &certInfoPtr->attributes,
						CRYPT_CERTTYPE_OCSP_RESPONSE, endPos - stell( stream ),
						&certInfoPtr->errorLocus, &certInfoPtr->errorType );

	/* In theory some OCSP responses can be sort of self-signed via attached
	   certs, but there are so many incompatible ways to delegate trust and 
	   signing authority mentioned in the RFC without any indication of 
	   which one implementors will follow that we require the user to supply 
	   the sig check certificate rather than assuming that some particular 
	   trust delegation mechanism will happen to be in place */
/*	certInfoPtr->flags |= CERT_FLAG_SELFSIGNED; */
	return( status );
	}

/* Read PKI user info */

static int readPkiUserInfo( STREAM *stream, CERT_INFO *userInfoPtr )
	{
	CRYPT_CONTEXT iCryptContext;
	CERT_PKIUSER_INFO *certUserInfo = userInfoPtr->cCertUser;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	ATTRIBUTE_LIST *attributeListCursor;
	QUERY_INFO queryInfo;
	STREAM userInfoStream;
	BYTE userInfo[ 128 ];
	int userInfoSize, length, status;

	/* Read the user name and encryption algorithm info and the start of the 
	   encrypted data */
	userInfoPtr->subjectDNptr = sMemBufPtr( stream );
	userInfoPtr->subjectDNsize = stell( stream );
	status = readDN( stream, &userInfoPtr->subjectName );
	userInfoPtr->subjectDNsize = stell( stream ) - userInfoPtr->subjectDNsize;
	if( cryptStatusOK( status ) )
		{
		readContextAlgoID( stream, NULL, &queryInfo, DEFAULT_TAG );
		status = readOctetString( stream, userInfo, &userInfoSize, 128 );
		if( cryptStatusOK( status ) && \
			userInfoSize != PKIUSER_ENCR_AUTHENTICATOR_SIZE )
			status = CRYPT_ERROR_BADDATA;
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Clone the CA key for our own use, load the IV from the encryption 
	   info, and use the cloned context to decrypt the user info.  We need to 
	   do this to prevent problems if multiple threads try to simultaneously 
	   decrypt with the CA key.  Since user objects aren't fully implemented 
	   yet, we use a fixed key as the CA key for now (most CA guidelines
	   merely require that the CA protect its user database via standard
	   (physical/ACL) security measures, so this is no less secure than what's
	   required by various CA guidelines).

	   When we do this for real we probably need an extra level of 
	   indirection to go from the CA secret to the database decryption key 
	   so that we can change the encryption algorithm and so that we don't 
	   have to directly apply the CA secret key to the user database */
	setMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, "interop interop interop ", 24 );
		status = krnlSendMessage( createInfo.cryptHandle,
								  IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_CTXINFO_KEY );
		iCryptContext = createInfo.cryptHandle;
		}
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, queryInfo.iv, queryInfo.ivLength );
		krnlSendMessage( iCryptContext,IMESSAGE_SETATTRIBUTE_S, &msgData, 
						 CRYPT_CTXINFO_IV );
		status = krnlSendMessage( iCryptContext, IMESSAGE_CTX_DECRYPT, 
								  userInfo, userInfoSize );
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Read the user info.  If we get a bad data error at this point we 
	   report it as a wrong decryption key rather than bad data since it's 
	   more likely to be the former */
	sMemConnect( &userInfoStream, userInfo, userInfoSize );
	readSequence( &userInfoStream, NULL );
	readOctetString( &userInfoStream, certUserInfo->pkiIssuePW, &length,
					 PKIUSER_AUTHENTICATOR_SIZE );
	status = readOctetString( &userInfoStream, certUserInfo->pkiRevPW, 
							  &length, PKIUSER_AUTHENTICATOR_SIZE );
	sMemDisconnect( &userInfoStream );
	zeroise( userInfo, userInfoSize );
	if( cryptStatusError( status ) )
		return( CRYPT_ERROR_WRONGKEY );

	/* Read the user ID and any other attributes */
	status = readAttributes( stream, &userInfoPtr->attributes, 
							 CRYPT_CERTTYPE_PKIUSER, sMemDataLeft( stream ),
							 &userInfoPtr->errorLocus, 
							 &userInfoPtr->errorType );
	if( cryptStatusError( status ) )
		return( status );

	/* In use the PKI user info is applied as a template to certificates to 
	   modify their contents before issue.  This is done by merging the
	   user info with the cert before it's issued.  Since there can be 
	   overlapping or conflicting attributes in the two objects, the ones in
	   the PKI user info are marked as locked to ensure that they override
	   any conflicting attributes that may be present in the cert */
	for( attributeListCursor = userInfoPtr->attributes;
		 attributeListCursor != NULL && \
			!isBlobAttribute( attributeListCursor );
		 attributeListCursor = attributeListCursor->next )
		attributeListCursor->flags |= ATTR_FLAG_LOCKED;
	
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Read Function Access Information					*
*																			*
****************************************************************************/

const CERTREAD_INFO certReadTable[] = {
	{ CRYPT_CERTTYPE_CERTIFICATE, readCertInfo },
	{ CRYPT_CERTTYPE_ATTRIBUTE_CERT, readAttributeCertInfo },
	{ CRYPT_CERTTYPE_CERTREQUEST, readCertRequestInfo },
	{ CRYPT_CERTTYPE_REQUEST_CERT, readCrmfRequestInfo },
	{ CRYPT_CERTTYPE_REQUEST_REVOCATION, readRevRequestInfo },
	{ CRYPT_CERTTYPE_CRL, readCRLInfo },
	{ CRYPT_CERTTYPE_CMS_ATTRIBUTES, readCmsAttributes },
	{ CRYPT_CERTTYPE_RTCS_REQUEST, readRtcsRequestInfo },
	{ CRYPT_CERTTYPE_RTCS_RESPONSE, readRtcsResponseInfo },
	{ CRYPT_CERTTYPE_OCSP_REQUEST, readOcspRequestInfo },
	{ CRYPT_CERTTYPE_OCSP_RESPONSE, readOcspResponseInfo },
	{ CRYPT_CERTTYPE_PKIUSER, readPkiUserInfo },
	{ CRYPT_ICERTTYPE_CMS_CERTSET, NULL },
	{ CRYPT_ICERTTYPE_SSL_CERTCHAIN, NULL },
	{ CRYPT_CERTTYPE_NONE, NULL }
	};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -