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

📄 pkcs15_wr.c

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

	/* Clean up */
	krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Add a certificate to a PKCS #15 collection, updating affected public and 
   private key attributes as required */

static int addCert( PKCS15_INFO *pkcs15infoPtr, 
					const CRYPT_CERTIFICATE cryptCert,
					const void *pubKeyAttributes, 
					const int pubKeyAttributeSize,
					const void *privKeyAttributes,
					const int privKeyAttributeSize,
					const CERTADD_TYPE certAddType )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE keyBuffer[ MAX_PRIVATE_KEYSIZE ];
	BYTE certAttributes[ KEYATTR_BUFFER_SIZE ];
	void *newPrivKeyData = pkcs15infoPtr->privKeyData;
#ifdef RETAIN_PUBKEY
	void *newPubKeyData = pkcs15infoPtr->pubKeyData;
#endif /* RETAIN_PUBKEY */
	void *newCertData = pkcs15infoPtr->certData;
	const int keyTypeTag = getKeyTypeTag( cryptCert );
	int newPrivKeyDataSize, newPrivKeyOffset, privKeyInfoSize;
#ifdef RETAIN_PUBKEY
	int newPubKeyDataSize, newPubKeyOffset, pubKeyInfoSize;
#endif /* RETAIN_PUBKEY */
	int newCertDataSize, newCertOffset, certAttributeSize;
	int status;

	/* If we've been passed a standalone cert, it has to be implicitly
	   trusted in order to be added */
	if( certAddType == CERTADD_STANDALONE_CERT )
		{
		int value;

		status = krnlSendMessage( cryptCert, IMESSAGE_GETATTRIBUTE,
								  &value, CRYPT_CERTINFO_TRUSTED_IMPLICIT );
		if( cryptStatusError( status ) || !value )
			return( CRYPT_ARGERROR_NUM1 );

		/* Set the personality type to cert-only */
		pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
		}

	/* Write the cert attributes */
	status = writeCertAttributes( certAttributes, &certAttributeSize,
								  pkcs15infoPtr, cryptCert );
	if( cryptStatusError( status ) )
		return( status );

	/* Find out how big the PKCS #15 data will be and allocate room for it.
	   Since the cert will affect the key attributes, we need to rewrite the
	   key information once we've done the cert.  If the rewritten key data
	   will fit into the existing space (for example if only a permission bit
	   or two has changed) we reuse the current storage, otherwise we
	   allocate new storage */
	if( certAddType == CERTADD_UPDATE_EXISTING )
		{
#ifdef RETAIN_PUBKEY
		pubKeyInfoSize = pkcs15infoPtr->pubKeyDataSize - \
						 pkcs15infoPtr->pubKeyOffset;
		newPubKeyDataSize = pubKeyAttributeSize + \
							( int ) sizeofObject( \
									  sizeofObject( \
										sizeofObject( pubKeyInfoSize ) ) );
		if( sizeofObject( newPubKeyDataSize ) > \
										pkcs15infoPtr->pubKeyDataSize )
			{
			newPubKeyData = \
					clAlloc( "addCert", \
							 ( int ) sizeofObject( newPubKeyDataSize ) );
			if( newPubKeyData == NULL )
				return( CRYPT_ERROR_MEMORY );
			}
#else
		if( pkcs15infoPtr->pubKeyData != NULL )
			{
			zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
			clFree( "addCert", pkcs15infoPtr->pubKeyData );
			pkcs15infoPtr->pubKeyData = NULL;
			pkcs15infoPtr->pubKeyDataSize = 0;
			}
#endif /* RETAIN_PUBKEY */
		privKeyInfoSize = pkcs15infoPtr->privKeyDataSize - \
						  pkcs15infoPtr->privKeyOffset;
		newPrivKeyDataSize = privKeyAttributeSize + \
							 ( int ) sizeofObject( \
									  sizeofObject( privKeyInfoSize ) );
		if( sizeofObject( newPrivKeyDataSize ) > \
										pkcs15infoPtr->privKeyDataSize )
			{
			newPrivKeyData = \
					clAlloc( "addCert", \
							 ( int ) sizeofObject( newPrivKeyDataSize ) );
			if( ( newPrivKeyData == NULL ) )
				{
#ifdef RETAIN_PUBKEY
				clFree( "addCert", newPubKeyData );
#endif /* RETAIN_PUBKEY */
				return( CRYPT_ERROR_MEMORY );
				}
			}
		}
	setMessageData( &msgData, keyBuffer, MAX_PRIVATE_KEYSIZE );
	status = krnlSendMessage( cryptCert, IMESSAGE_CRT_EXPORT, &msgData, 
							  CRYPT_CERTFORMAT_CERTIFICATE );
	if( cryptStatusOK( status ) )
		{
		newCertDataSize = ( int ) sizeofObject( \
										certAttributeSize + \
										sizeofObject( \
											sizeofObject( msgData.length ) ) );
		if( newCertDataSize > pkcs15infoPtr->certDataSize )
			{
			newCertData = clAlloc( "addCert", newCertDataSize );
			if( newCertData == NULL )
				status = CRYPT_ERROR_MEMORY;
			}
		}
	if( cryptStatusOK( status ) )
		{
		sMemOpen( &stream, newCertData, newCertDataSize );
		writeSequence( &stream, certAttributeSize + \
					   ( int ) sizeofObject( sizeofObject( msgData.length ) ) );
		swrite( &stream, certAttributes, certAttributeSize );
		writeConstructed( &stream, ( int ) sizeofObject( msgData.length ),
						  CTAG_OB_TYPEATTR );
		writeSequence( &stream, msgData.length );
		newCertOffset = stell( &stream );
		swrite( &stream, keyBuffer, msgData.length );
		assert( sStatusOK( &stream ) );
		sMemDisconnect( &stream );
		}
	if( cryptStatusError( status ) )
		{
		/* Undo what we've done so far without changing the existing PKCS #15
		   data */
#ifdef RETAIN_PUBKEY
		if( newPubKeyData != pkcs15infoPtr->pubKeyData )
			clFree( "addCert", newPubKeyData );
#endif /* RETAIN_PUBKEY */
		if( newPrivKeyData != pkcs15infoPtr->privKeyData )
			clFree( "addCert", newPrivKeyData );
		if( newCertData != pkcs15infoPtr->certData && newCertData != NULL )
			clFree( "addCert", newCertData );
		return( status );
		}

	/* Replace the old cert (if there is one) with the new cert.  If it's an
	   add of a standalone cert, we're done */
	if( newCertData != pkcs15infoPtr->certData )
		{
		if( pkcs15infoPtr->certData != NULL )
			{
			zeroise( pkcs15infoPtr->certData, pkcs15infoPtr->certDataSize );
			clFree( "addCert", pkcs15infoPtr->certData );
			}
		pkcs15infoPtr->certData = newCertData;
		}
	pkcs15infoPtr->certDataSize = newCertDataSize;
	pkcs15infoPtr->certOffset = newCertOffset;
	if( certAddType != CERTADD_UPDATE_EXISTING )
		return( CRYPT_OK );

#ifdef RETAIN_PUBKEY
	assert( pubKeyInfoSize < MAX_PRIVATE_KEYSIZE );
#endif /* RETAIN_PUBKEY */
	assert( privKeyInfoSize < MAX_PRIVATE_KEYSIZE );

	/* The corresponding key is already present, we need to update the key
	   info since adding the certificate may have changed the attributes.
	   First we write the new attributes and append the existing key info.
	   Since we may be doing an in-place update, we copy the data out to a
	   temporary buffer while we make the changes */
#ifdef RETAIN_PUBKEY
	memcpy( keyBuffer, ( BYTE * ) pkcs15infoPtr->pubKeyData +
								  pkcs15infoPtr->pubKeyOffset, 
			pubKeyInfoSize );
	sMemOpen( &stream, newPubKeyData,
			  ( int ) sizeofObject( newPubKeyDataSize ) );
	writeConstructed( &stream, newPubKeyDataSize, keyTypeTag );
	swrite( &stream, pubKeyAttributes, pubKeyAttributeSize );
	writeConstructed( &stream,
					  ( int ) sizeofObject( sizeofObject( pubKeyInfoSize ) ),
					  CTAG_OB_TYPEATTR );
	writeSequence( &stream, ( int ) sizeofObject( pubKeyInfoSize ) );
	writeConstructed( &stream, pubKeyInfoSize, CTAG_OV_DIRECT );
	newPubKeyOffset = stell( &stream );
	swrite( &stream, keyBuffer, pubKeyInfoSize );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );
#endif /* RETAIN_PUBKEY */
	memcpy( keyBuffer, ( BYTE * ) pkcs15infoPtr->privKeyData +
								  pkcs15infoPtr->privKeyOffset, 
			privKeyInfoSize );
	sMemOpen( &stream, newPrivKeyData,
			  ( int ) sizeofObject( newPrivKeyDataSize ) );
	writeConstructed( &stream, newPrivKeyDataSize, keyTypeTag );
	swrite( &stream, privKeyAttributes, privKeyAttributeSize );
	writeConstructed( &stream, ( int ) sizeofObject( privKeyInfoSize ),
					  CTAG_OB_TYPEATTR );
	writeSequence( &stream, privKeyInfoSize );
	newPrivKeyOffset = stell( &stream );
	swrite( &stream, keyBuffer, privKeyInfoSize );
	assert( sStatusOK( &stream ) );
	sMemDisconnect( &stream );
	zeroise( keyBuffer, MAX_PRIVATE_KEYSIZE );

	/* Replace the old data with the newly-written data */
#ifdef RETAIN_PUBKEY
	if( newPubKeyData != pkcs15infoPtr->pubKeyData )
		{
		zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
		clFree( "addCert", pkcs15infoPtr->pubKeyData );
		pkcs15infoPtr->pubKeyData = newPubKeyData;
		}
#endif /* RETAIN_PUBKEY */
	if( newPrivKeyData != pkcs15infoPtr->privKeyData )
		{
		zeroise( pkcs15infoPtr->privKeyData, pkcs15infoPtr->privKeyDataSize );
		clFree( "addCert", pkcs15infoPtr->privKeyData );
		pkcs15infoPtr->privKeyData = newPrivKeyData;
		}
#ifdef RETAIN_PUBKEY
	pkcs15infoPtr->pubKeyDataSize = ( int ) sizeofObject( newPubKeyDataSize );
	pkcs15infoPtr->pubKeyOffset = newPubKeyOffset;
#endif /* RETAIN_PUBKEY */
	pkcs15infoPtr->privKeyDataSize = ( int ) sizeofObject( newPrivKeyDataSize );
	pkcs15infoPtr->privKeyOffset = newPrivKeyOffset;

	return( CRYPT_OK );
	}

/* Add a complete cert chain to a PKCS #15 collection */

static int addCertChain( PKCS15_INFO *pkcs15info, 
						 const CRYPT_CERTIFICATE iCryptCert )
	{
	BOOLEAN seenNonDuplicate = FALSE;
	int status;

	/* See if there are certs in the chain beyond the first one, which we've
	   already added.  Getting a data not found error is OK since it just
	   means that there are no more certs present */
	krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
					 MESSAGE_VALUE_CURSORFIRST,
					 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_CURSORNEXT,
							  CRYPT_CERTINFO_CURRENT_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ERROR_NOTFOUND ) ? CRYPT_OK : status );

	/* Walk up the chain checking each cert to see whether we need to add
	   it */
	do
		{
		PKCS15_INFO *pkcs15infoPtr;
		BYTE iAndSID [ CRYPT_MAX_HASHSIZE ];
		int i;

		/* Check whether this cert is present */
		status = getCertID( iCryptCert, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER,
							iAndSID );
		if( cryptStatusError( status ) )
			continue;
		if( findEntry( pkcs15info, CRYPT_IKEYID_ISSUERID, iAndSID,
					   KEYID_SIZE, KEYMGMT_FLAG_NONE ) != NULL )
			continue;

		/* We've found a cert that isn't present yet, try and add it */
		for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
			if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
				break;
		if( i == MAX_PKCS15_OBJECTS )
			return( CRYPT_ERROR_OVERFLOW );
		pkcs15infoPtr = &pkcs15info[ i ];
		pkcs15infoPtr->index = i;
		pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
		status = addCert( pkcs15infoPtr, iCryptCert, NULL, 0, NULL, 0, 
						  CERTADD_NORMAL );

		/* A cert being added may already be present, however we can't fail
		   immediately because there may be further certs in the chain, so we
		   keep track of whether we've successfully added at least one cert
		   and clear data duplicate errors */
		if( status == CRYPT_OK )
			seenNonDuplicate = TRUE;
		else
			if( status == CRYPT_ERROR_DUPLICATE )
				status = CRYPT_OK;
		}
	while( cryptStatusOK( status ) && \
		   krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
							MESSAGE_VALUE_CURSORNEXT,
							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK );
	if( cryptStatusOK( status ) && !seenNonDuplicate )
		/* We reached the end of the chain without finding anything we could
		   add, return a data duplicate error */
		status = CRYPT_ERROR_DUPLICATE;
	return( status );
	}

/* Add a public key to a PKCS #15 collection */

static int addPublicKey( PKCS15_INFO *pkcs15info, 
						 const CRYPT_HANDLE cryptHandle,
						 const void *pubKeyAttributes, 
						 const int pubKeyAttributeSize,
						 const CRYPT_ALGO_TYPE pkcCryptAlgo,
						 const int modulusSize )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	const int keyTypeTag = getKeyTypeTag( cryptHandle );
	int pubKeyDataSize, extraDataSize = 0, status;

	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData, 
							  CRYPT_IATTRIBUTE_KEY_SPKI );
	pubKeyDataSize = msgData.length;
	if( pkcCryptAlgo == CRYPT_ALGO_RSA )
		/* RSA keys have an extra element for PKCS #11 compatibility */
		extraDataSize = sizeofShortInteger( modulusSize );
	if( cryptStatusOK( status ) )
		{
		pkcs15info->pubKeyDataSize = ( int ) sizeofObject( \
									pubKeyAttributeSize + \

⌨️ 快捷键说明

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