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

📄 chain.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
		   once we've got all the certs and know which cert is the leaf, we 
		   can go back and decode the public key information for it */
		status = importCert( sMemBufPtr( stream ), sMemDataLeft( stream ),
							 &iNewCert, cryptOwner, CRYPT_KEYID_NONE,
							 NULL, 0, dataOnlyCert ? \
								CERTFORMAT_DATAONLY : \
								CRYPT_CERTTYPE_CERTIFICATE );
		if( cryptStatusOK( status ) )
			{
			RESOURCE_DATA msgData;

			/* Add the newly-read cert to the chain and skip over its
			   encoded data.  Unfortunately due to the mixing of stream and 
			   non-stream functions we have to do this in a somewhat 
			   roundabout manner by getting the length of the data in the 
			   newly-created cert object and then skipping that far ahead in
			   the input stream */
			iCertChain[ certChainEnd++ ] = iNewCert;
			setMessageData( &msgData, NULL, 0 );
			status = krnlSendMessage( iNewCert, IMESSAGE_CRT_EXPORT, 
									  &msgData, CRYPT_CERTFORMAT_CERTIFICATE );
			if( cryptStatusOK( status ) )
				status = sSkip( stream, msgData.length );
			}
		if( cryptStatusError( status ) )
			{
			if( certChainEnd > 0 )
				freeCertChain( iCertChain, certChainEnd );
			return( status );
			}

		/* If it's encoded using the indefinite form and we find the EOC
		   octets, exit */
		if( certSequenceLength == CRYPT_UNUSED )
			{
			status = checkEOC( stream );
			if( cryptStatusError( status ) )
				return( status );
			if( status == TRUE )
				/* We've seen EOC octets, we're done */
				break;
			}
		}

	/* We must have read at least one cert in order to create a chain */
	if( certChainEnd <= 0 )
		return( CRYPT_ERROR_BADDATA );

	/* Build the complete chain from the individual certs */
	return( buildCertChain( iCryptCert, iCertChain, certChainEnd, 
							keyIDtype, keyID, keyIDlength ) );
	}

/* Fetch a sequence of certs from an object to create a cert chain */

int assembleCertChain( CRYPT_CERTIFICATE *iCertificate,
					   const CRYPT_HANDLE iCertSource, 
					   const CRYPT_KEYID_TYPE keyIDtype,
					   const void *keyID, const int keyIDlength,
					   const int options )
	{
	CRYPT_CERTIFICATE iCertChain[ MAX_CHAINLENGTH ], lastCert;
	MESSAGE_KEYMGMT_INFO getnextcertInfo;
	const int chainOptions = options & KEYMGMT_FLAG_DATAONLY_CERT;
	int stateInfo = CRYPT_ERROR, certChainEnd = 1, status;

	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
	assert( isHandleRangeValid( iCertSource ) );
	assert( isReadPtr( keyID, keyIDlength ) && keyIDlength > 1 );

	/* Get the initial cert based on the key ID */
	setMessageKeymgmtInfo( &getnextcertInfo, keyIDtype, keyID, keyIDlength, 
						   &stateInfo, sizeof( int ), 
						   options & KEYMGMT_MASK_CERTOPTIONS );
	status = krnlSendMessage( iCertSource, IMESSAGE_KEY_GETFIRSTCERT,
							  &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );
	if( cryptStatusError( status ) )
		return( status );
	iCertChain[ 0 ] = lastCert = getnextcertInfo.cryptHandle;

	/* Fetch subsequent certs that make up the chain based on the state
	   information.  Since the basic options apply only to the leaf cert,
	   we only allow the data-only-cert flag at this point */
	setMessageKeymgmtInfo( &getnextcertInfo, CRYPT_KEYID_NONE, NULL, 0, 
						   &stateInfo, sizeof( int ), chainOptions );
	while( cryptStatusOK( status ) )
		{
		int selfSigned;

		/* If we've reached a self-signed (CA root) cert, stop.  Note that
		   this can't detect PKIX path-kludge certs, which look identical
		   to CA root certs and can only be reliably identified if they're
		   present in the middle of a pre-built chain */
		status = krnlSendMessage( lastCert, IMESSAGE_GETATTRIBUTE, 
								  &selfSigned, CRYPT_CERTINFO_SELFSIGNED );
		if( cryptStatusError( status ) || selfSigned )
			break;

		/* Get the next cert in the chain from the source, import it, and 
		   add it to the collection */
		getnextcertInfo.cryptHandle = CRYPT_ERROR;	/* Reset result handle */
		status = krnlSendMessage( iCertSource, IMESSAGE_KEY_GETNEXTCERT,
								  &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusError( status ) )
			break;

		/* Make sure that we don't overflow the chain */
		if( certChainEnd >= MAX_CHAINLENGTH )
			{
			krnlSendNotifier( getnextcertInfo.cryptHandle,
							  IMESSAGE_DECREFCOUNT );
			status = CRYPT_ERROR_OVERFLOW;
			break;
			}

		iCertChain[ certChainEnd++ ] = lastCert = getnextcertInfo.cryptHandle;
		}
	if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTFOUND )
		{
		freeCertChain( iCertChain, certChainEnd );
		return( status );
		}

	/* Build the complete chain from the individual certs */
	return( buildCertChain( iCertificate, iCertChain, certChainEnd, 
							CRYPT_KEYID_NONE, NULL, 0 ) );
	}

/****************************************************************************
*																			*
*						Write Certificate-bagging Records					*
*																			*
****************************************************************************/

/* Determine the size of and write a certificate path from a base cert up to 
   the root */

static int sizeofCertPath( const CERT_INFO *certInfoPtr,
						   int *certSizeInfo )
	{
	int length = 0, i;

	/* Evaluate the size of the current certificate and the issuer 
	   certificates in the chain.  If it's a cert collection, it's just a 
	   container for random certs but not a cert in its own right, so we 
	   skip the leaf cert */
	if( !( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION ) )
		{
		length = certInfoPtr->certificateSize;
		if( certSizeInfo != NULL )
			length += 3;
		}
	for( i = 0; i < certInfoPtr->cCertCert->chainEnd; i++ )
		{
		RESOURCE_DATA msgData;
		int status;

		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( certInfoPtr->cCertCert->chain[ i ], 
								  IMESSAGE_CRT_EXPORT, &msgData, 
								  CRYPT_CERTFORMAT_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		length += msgData.length;
		if( certSizeInfo != NULL )
			{
			certSizeInfo[ i ] = msgData.length;
			length += 3;
			}
		}

	return( length );
	}

static int writeCertPath( STREAM *stream, const CERT_INFO *certInfoPtr,
						  int *certSizeInfo )

	{
	int i, status = CRYPT_OK;

	/* Write the current certificate and the associated cert chain up to the
	   root.  If it's a cert collection, it's just a container for random 
	   certs but not a cert in its own right, so we skip the leaf cert */
	if( !( certInfoPtr->flags & CERT_FLAG_CERTCOLLECTION ) )
		{
		if( certSizeInfo != NULL )
			{
			sputc( stream, 0 );
			writeUint16( stream, certInfoPtr->certificateSize );
			}
		status = swrite( stream, certInfoPtr->certificate, 
						 certInfoPtr->certificateSize );
		}
	for( i = 0; cryptStatusOK( status ) && \
				i < certInfoPtr->cCertCert->chainEnd; i++ )
		{
		if( certSizeInfo != NULL )
			{
			sputc( stream, 0 );
			writeUint16( stream, certSizeInfo[ i ] );
			}
		status = exportCertToStream( stream,
									 certInfoPtr->cCertCert->chain[ i ], 
									 CRYPT_CERTTYPE_CERTIFICATE );
		}

	return( status );
	}

/* Write certificate chain/sequence information:

	CertChain ::= SEQUENCE {
		contentType				OBJECT IDENTIFIER,	-- signedData
		content			  [ 0 ]	EXPLICIT SEQUENCE {
			version				INTEGER (1),
			digestAlgorithms	SET OF AlgorithmIdentifier,	-- SIZE(0)
			contentInfo			SEQUENCE {
				signedData		OBJECT IDENTIFIER	-- data
				}
			certificates  [ 0 ]	SET OF {
									Certificate
				}
			}
		signerInfos				SET OF SignerInfo			-- SIZE(0)
		} */

int sizeofCertCollection( const CERT_INFO *certInfoPtr,
						  const CRYPT_CERTFORMAT_TYPE certFormatType )
	{
	assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
	assert( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \
			certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \
			certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );

	if( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN )
		{
		int certSizeInfo[ MAX_CHAINLENGTH ];

		return( sizeofCertPath( certInfoPtr, certSizeInfo ) );
		}
	return( sizeofObject( sizeofCertPath( certInfoPtr, NULL ) ) );
	}

int writeCertCollection( STREAM *stream, const CERT_INFO *certInfoPtr,
						 const CRYPT_CERTFORMAT_TYPE certFormatType )
	{
	int certSizeInfo[ MAX_CHAINLENGTH ];
	int *certSizePtr = \
			( certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN ) ? \
			certSizeInfo : NULL;
	const int certCollectionLength = sizeofCertPath( certInfoPtr, \
													 certSizePtr );

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( certInfoPtr, sizeof( CERT_INFO ) ) );
	assert( certFormatType == CRYPT_ICERTFORMAT_CERTSET || \
			certFormatType == CRYPT_ICERTFORMAT_CERTSEQUENCE || \
			certFormatType == CRYPT_ICERTFORMAT_SSL_CERTCHAIN );

	if( cryptStatusError( certCollectionLength ) )
		return( certCollectionLength );
	switch( certFormatType )
		{
		case CRYPT_ICERTFORMAT_CERTSET:
			writeConstructed( stream, certCollectionLength, 0 );
			break;

		case CRYPT_ICERTFORMAT_CERTSEQUENCE:
			writeSequence( stream, certCollectionLength );
			break;

		case CRYPT_ICERTFORMAT_SSL_CERTCHAIN:
			break;

		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR_NOTAVAIL );
		}
	return( writeCertPath( stream, certInfoPtr, certSizePtr ) );
	}

int writeCertChain( STREAM *stream, const CERT_INFO *certInfoPtr )
	{
	const int certSetLength = sizeofCertPath( certInfoPtr, NULL );
	int innerLength, status;

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

	if( cryptStatusError( certSetLength ) )
		return( certSetLength );

	/* Determine how big the encoded cert chain/sequence will be */
	innerLength = sizeofShortInteger( 1 ) + ( int ) sizeofObject( 0 ) + \
					  ( int ) sizeofObject( sizeofOID( OID_CMS_DATA ) ) + \
					  ( int ) sizeofObject( certSetLength ) + \
					  ( int ) sizeofObject( 0 );

	/* Write the outer SEQUENCE wrapper and contentType and content wrapper */
	writeSequence( stream, 
				   sizeofOID( OID_CMS_SIGNEDDATA ) + \
					( int ) sizeofObject( sizeofObject( innerLength ) ) );
	swrite( stream, OID_CMS_SIGNEDDATA, sizeofOID( OID_CMS_SIGNEDDATA ) );
	writeConstructed( stream, sizeofObject( innerLength ), 0 );
	writeSequence( stream, innerLength );

	/* Write the inner content */
	writeShortInteger( stream, 1, DEFAULT_TAG );
	writeSet( stream, 0 );
	writeSequence( stream, sizeofOID( OID_CMS_DATA ) );
	swrite( stream, OID_CMS_DATA, sizeofOID( OID_CMS_DATA ) );
	writeConstructed( stream, certSetLength, 0 );
	status = writeCertPath( stream, certInfoPtr, NULL );
	if( cryptStatusOK( status ) )
		status = writeSet( stream, 0 );
	return( status );
	}

⌨️ 快捷键说明

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