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

📄 certchn.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	   signed */
	status = krnlSendMessage( certChainPtr->certChain[ certChainEnd - 1 ], 
							  RESOURCE_IMESSAGE_GETATTRIBUTE, &selfSigned,
							  CRYPT_CERTINFO_SELFSIGNED );
	if( cryptStatusOK( status ) && selfSigned )
		certChainPtr->flags |= CERT_FLAG_SELFSIGNED;
	unlockResource( certChainPtr );

	return( CRYPT_OK );
	}

/* Read certificate chain/sequence information */

int readCertChain( STREAM *stream, CRYPT_CERTIFICATE *iCryptCert,
				   const CRYPT_USER cryptOwner,
				   const CRYPT_CERTTYPE_TYPE type,
				   const CRYPT_KEYID_TYPE keyIDtype,
				   const void *keyID, const int keyIDlength,
				   const BOOLEAN dataOnlyCert )
	{
	CRYPT_CERTIFICATE iCertChain[ MAX_CHAINLENGTH ];
	int certSequenceLength, endPos, certChainEnd = 0, status;

	assert( type == CRYPT_CERTTYPE_CERTCHAIN || \
			type == CRYPT_CERTTYPE_CMS_CERTSET || \
			type == CRYPT_CERTTYPE_SSL_CERTCHAIN );
	assert( ( keyIDtype == CRYPT_KEYID_NONE && keyID == NULL && \
			  keyIDlength == 0 ) || \
			( ( keyIDtype == CRYPT_IKEYID_KEYID || \
				keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER ) && \
			  keyID != NULL && keyIDlength > 16 ) );

	/* If it's a PKCS #7 chain, skip the contentType OID, read the content 
	   encapsulation and header if necessary, and burrow into the PKCS #7 
	   content */
	if( type == CRYPT_CERTTYPE_CERTCHAIN )
		{
		long integer;
		int length;

		/* Read the wrapper */
		readUniversal( stream );
		readConstructed( stream, NULL, 0 );
		readSequence( stream, NULL );

		/* Read the version number (1 = PKCS #7 v1.5, 2 = PKCS #7 v1.6,
		   3 = S/MIME with attribute certificate(s)), empty SET OF
		   DigestAlgorithmIdentifier, and ContentInfo header */
		readShortInteger( stream, &integer );
		status = readSet( stream, &length );
		if( cryptStatusOK( status ) && ( integer < 1 || integer > 3 ) )
			status = CRYPT_ERROR_BADDATA;
		if( cryptStatusError( status ) )
			return( status );
		if( length > 0 )
			sSkip( stream, length );

		/* Read the ContentInfo header, contentType OID and the inner content
		   encapsulation */
		readSequence( stream, NULL );
		status = readOID( stream, OID_CMS_DATA );
		if( cryptStatusError( status ) )
			return( status );
		checkEOC( stream );
		}
	if( type == CRYPT_CERTTYPE_CERTCHAIN || \
		type == CRYPT_CERTTYPE_CMS_CERTSET )
		{
		status = readConstructed( stream, &certSequenceLength, 0 );
		if( cryptStatusError( status ) )
			return( status );
		}
	else
		/* There's no outer wrapper to give us length information for an SSL
		   cert chain, however the length will be equal to the total stream
		   size */
		certSequenceLength = sMemBufSize( stream );
	endPos = ( int ) ( stell( stream ) + certSequenceLength );

	/* We've finally reached the certificate(s), read the collection of certs
	   into cert objects.  We allow for a bit of slop for software which gets 
	   the length encoding wrong by a few bytes */
	while( !certSequenceLength || \
		   stell( stream ) <= endPos - MIN_ATTRIBUTE_SIZE )
		{
		CRYPT_CERTIFICATE iNewCert;

		/* Make sure we don't overflow the chain */
		if( certChainEnd >= MAX_CHAINLENGTH )
			{
			freeCertChain( iCertChain, certChainEnd );
			return( CRYPT_ERROR_OVERFLOW );
			}

		/* If it's an SSL cert chain, there's a 24-bit length field between
		   certs */
		if( type == CRYPT_CERTTYPE_SSL_CERTCHAIN )
			sSkip( stream, 3 );

		/* Read the next cert and add it to the chain.  When importing the
		   chain from an external (untrusted) source we create standard certs
		   so we can check the signatures on each link in the chain.  When
		   importing from a trusted source we create data-only certs, 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 : CERTFORMAT_NORMAL );
		if( !cryptStatusError( status ) )
			{
			iCertChain[ certChainEnd++ ] = iNewCert;
			status = sSkip( stream, status );
			}
		if( cryptStatusError( status ) )
			{
			freeCertChain( iCertChain, certChainEnd );
			return( status );
			}

		/* If it's encoded using the indefinite form and we find the EOC
		   octets, exit */
		if( !certSequenceLength && checkEOC( stream ) )
			break;
		}

	/* 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;

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

	/* Fetch subsequent certs which 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 );
	do
		{
		int selfSigned;

		/* If we've reached a self-signed cert, stop */
		krnlSendMessage( lastCert, RESOURCE_IMESSAGE_GETATTRIBUTE, 
						 &selfSigned, CRYPT_CERTINFO_SELFSIGNED );
		if( 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, RESOURCE_IMESSAGE_KEY_GETNEXTCERT,
								  &getnextcertInfo, KEYMGMT_ITEM_PUBLICKEY );
		if( cryptStatusOK( status ) )
			{
			if( certChainEnd >= MAX_CHAINLENGTH )
				status = CRYPT_ERROR_OVERFLOW;
			else
				iCertChain[ certChainEnd++ ] = \
							lastCert = getnextcertInfo.cryptHandle;
			}
		if( status == CRYPT_ERROR_NOTFOUND )
			{
			status = CRYPT_OK;
			break;	/* End of chain reached */
			}
		}
	while( cryptStatusOK( status ) );
	if( cryptStatusError( status ) )
		{
		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 sequence of certificates from a base
   cert up to the root */

static int sizeofCertSequence( const CERT_INFO *certInfoPtr )
	{
	int length = certInfoPtr->certificateSize, i;

	/* Evaluate the size of the issuer certificates in the chain */
	for( i = 0; i < certInfoPtr->certChainEnd; i++ )
		{
		CERT_INFO *certChainPtr;

		getCheckInternalResource( certInfoPtr->certChain[ i ], certChainPtr,
        						  OBJECT_TYPE_CERTIFICATE );
		length += certChainPtr->certificateSize;
		unlockResource( certChainPtr );
		}

	return( length );
	}

static int writeCertSequence( STREAM *stream, const CERT_INFO *certInfoPtr )
	{
	int i, status;

	/* Write the current certificate and the associated cert chain up to the
	   root */
	swrite( stream, certInfoPtr->certificate, certInfoPtr->certificateSize );
	for( i = 0; i < certInfoPtr->certChainEnd; i++ )
		{
		CERT_INFO *certChainPtr;

		getCheckInternalResource( certInfoPtr->certChain[ i ], certChainPtr,
        						  OBJECT_TYPE_CERTIFICATE );
		status = swrite( stream, certChainPtr->certificate,
						 certChainPtr->certificateSize );
		unlockResource( certChainPtr );
		}

	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 ]	IMPLICIT SET OF {
									Certificate
				}
			}
		signerInfos				SET OF SignerInfo			-- SIZE(0)
		} */

int sizeofCertSet( const CERT_INFO *certInfoPtr )
	{
	return( ( int ) sizeofObject( sizeofCertSequence( certInfoPtr ) ) );
	}

int writeCertSet( STREAM *stream, const CERT_INFO *certInfoPtr )
	{
	writeConstructed( stream, sizeofCertSequence( certInfoPtr ), 0 );
	return( writeCertSequence( stream, certInfoPtr ) );
	}

int writeCertChain( STREAM *stream, const CERT_INFO *certInfoPtr )
	{
	int innerLength;

	/* Determine how big the encoded cert chain/sequence will be */
	innerLength = sizeofShortInteger( 1 ) + ( int ) sizeofObject( 0 ) + \
					  ( int ) sizeofObject( sizeofOID( OID_CMS_DATA ) ) + \
					  ( int ) sizeofObject( sizeofCertSequence( certInfoPtr ) ) + \
					  ( 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 ) );
	writeCertSet( stream, certInfoPtr );
	return( writeSet( stream, 0 ) );
	}

⌨️ 快捷键说明

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