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

📄 read.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
								 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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readOcspRequestInfo( INOUT STREAM *stream, 
								INOUT CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	int length, endPos, fieldsProcessed, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* 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( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
									 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 );
	for( fieldsProcessed = 0;
		 cryptStatusOK( status ) && length > MIN_ATTRIBUTE_SIZE && \
			fieldsProcessed < FAILSAFE_ITERATIONS_LARGE;
		 fieldsProcessed++ )
		{
		const int innerStartPos = stell( stream );

		status = readOcspRequestEntry( stream, &certRevInfo->revocations,
									   certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusOK( status ) && \
		fieldsProcessed >= FAILSAFE_ITERATIONS_LARGE )
		status = CRYPT_ERROR_OVERFLOW;
	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 ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readOcspResponseInfo( INOUT STREAM *stream, 
								 INOUT CERT_INFO *certInfoPtr )
	{
	CERT_REV_INFO *certRevInfo = certInfoPtr->cCertRev;
	time_t dummyTime;
	int length, endPos, fieldsProcessed, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( certInfoPtr, sizeof( CERT_INFO ) ) );

	/* 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( certErrorReturn( certInfoPtr, CRYPT_CERTINFO_VERSION,
									 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 );
		}
	status = readGeneralizedTime( stream, &dummyTime );	/* producedAt */
	if( cryptStatusError( status ) )
		return( status );

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

		status = readOcspResponseEntry( stream, &certRevInfo->revocations,
										certInfoPtr );
		length -= stell( stream ) - innerStartPos;
		}
	if( cryptStatusOK( status ) && \
		fieldsProcessed >= FAILSAFE_ITERATIONS_LARGE )
		status = CRYPT_ERROR_OVERFLOW;
	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
	   certificates 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 signature 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 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readPkiUserInfo( INOUT STREAM *stream, 
							INOUT CERT_INFO *userInfoPtr )
	{
	CRYPT_CONTEXT iCryptContext;
	CERT_PKIUSER_INFO *certUserInfo = userInfoPtr->cCertUser;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	ATTRIBUTE_LIST *attributeListCursor;
	MESSAGE_DATA msgData;
	QUERY_INFO queryInfo;
	STREAM userInfoStream;
	BYTE userInfo[ 128 + 8 ];
	int userInfoSize = DUMMY_INIT, length, iterationCount, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( userInfoPtr, sizeof( CERT_INFO ) ) );

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

	/* 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.  See the comment in write.c for the use of
	   the fixed interop key */
	setMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	iCryptContext = createInfo.cryptHandle;
	setMessageData( &msgData, "interop interop interop ", 24 );
	status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, 
							  &msgData, CRYPT_CTXINFO_KEY );
	if( cryptStatusOK( status ) )
		{
		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, PKIUSER_AUTHENTICATOR_SIZE );
	status = readOctetString( &userInfoStream, certUserInfo->pkiRevPW,
							  &length, PKIUSER_AUTHENTICATOR_SIZE, 
							  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 );

	/* As used by cryptlib 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 certificate 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 certificate */
	for( attributeListCursor = userInfoPtr->attributes, iterationCount = 0;
		 attributeListCursor != NULL && \
			!isBlobAttribute( attributeListCursor ) && \
			iterationCount < FAILSAFE_ITERATIONS_MAX; 
		 attributeListCursor = attributeListCursor->next, iterationCount++ )
		attributeListCursor->flags |= ATTR_FLAG_LOCKED;
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	return( CRYPT_OK );
	}

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

typedef struct {
	const CRYPT_CERTTYPE_TYPE type;
	const READCERT_FUNCTION function;
	} CERTREAD_INFO;
static const CERTREAD_INFO FAR_BSS 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 }, { CRYPT_CERTTYPE_NONE, NULL }
	};

CHECK_RETVAL_PTR \
READCERT_FUNCTION getCertReadFunction( IN_ENUM( CRYPT_CERTTYPE ) \
										const CRYPT_CERTTYPE_TYPE certType )
	{
	int i;

	REQUIRES_N( certType > CRYPT_CERTTYPE_NONE && certType < CRYPT_CERTTYPE_LAST );

	for( i = 0; 
		 certReadTable[ i ].type != CRYPT_CERTTYPE_NONE && \
			i < FAILSAFE_ARRAYSIZE( certReadTable, CERTREAD_INFO ); 
		 i++ )
		{
		if( certReadTable[ i ].type == certType )
			return( certReadTable[ i ].function );
		}
	ENSURES_N( i < FAILSAFE_ARRAYSIZE( certReadTable, CERTREAD_INFO ) );

	return( NULL );
	}

⌨️ 快捷键说明

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