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

📄 pkcs15_adpb.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					cryptlib PKCS #15 Public-key Add Interface				*
*						Copyright Peter Gutmann 1996-2007					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "keyset.h"
  #include "pkcs15.h"
  #include "asn1.h"
#else
  #include "crypt.h"
  #include "keyset/keyset.h"
  #include "keyset/pkcs15.h"
  #include "misc/asn1.h"
#endif /* Compiler-specific includes */

#ifdef USE_PKCS15

/* Define the following to use the post-PKCS #15 draft encapsulation for
   certificates.  Note that this will break backwards compatibility for
   cryptlib versions before 3.3.0 (which dates from late 2006) because 
   earlier versions (likewise for backwards compatibility) still read and 
   wrote the original form */

/* #define POST_DRAFT_ENCAPSULATION */

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* Calculate the size of and if necessary allocate storage for public-key 
   and certificate data */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int calculatePubkeyStorage( const PKCS15_INFO *pkcs15infoPtr,
								   OUT_PTR void **newPubKeyDataPtr, 
								   OUT_LENGTH_SHORT_Z int *newPubKeyDataSize, 
								   IN_LENGTH_SHORT const int pubKeySize,
								   IN_LENGTH_SHORT const int pubKeyAttributeSize,
								   IN_LENGTH_SHORT const int extraDataSize )
	{
	void *newPubKeyData;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isWritePtr( newPubKeyDataPtr, sizeof( void * ) ) );
	assert( isWritePtr( newPubKeyDataSize, sizeof( int ) ) ); 

	REQUIRES( pubKeySize > 0 && pubKeySize < MAX_INTLENGTH_SHORT );
	REQUIRES( pubKeyAttributeSize > 0 && \
			  pubKeyAttributeSize < MAX_INTLENGTH_SHORT );
	REQUIRES( extraDataSize >= 0 && extraDataSize < MAX_INTLENGTH_SHORT );

	/* Calculate the new private-key data size */
	*newPubKeyDataSize = sizeofObject( \
							pubKeyAttributeSize + \
							sizeofObject( \
								sizeofObject( \
									sizeofObject( pubKeySize ) + \
									extraDataSize ) ) );

	/* If the new data will fit into the existing storage, we're done */
	if( *newPubKeyDataSize <= pkcs15infoPtr->pubKeyDataSize )
		return( CRYPT_OK );

	/* Allocate storage for the new data */
	newPubKeyData = clAlloc( "calculatePubkeyStorage", *newPubKeyDataSize );
	if( newPubKeyData == NULL )
		return( CRYPT_ERROR_MEMORY );
	*newPubKeyDataPtr = newPubKeyData;

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int calculateCertStorage( const PKCS15_INFO *pkcs15infoPtr,
								 OUT_PTR void **newCertDataPtr, 
								 OUT_LENGTH_SHORT_Z int *newCertDataSize,
								 IN_LENGTH_SHORT const int certAttributeSize,
								 IN_LENGTH_SHORT const int certSize )
	{
	void *newCertData;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isWritePtr( newCertDataPtr, sizeof( void * ) ) );
	assert( isWritePtr( newCertDataSize, sizeof( int ) ) ); 

	REQUIRES( certAttributeSize > 0 && \
			  certAttributeSize < MAX_INTLENGTH_SHORT );
	REQUIRES( certSize > 0 && certSize < MAX_INTLENGTH_SHORT );

	/* Calculate the new certificate data size */
	*newCertDataSize = sizeofObject( certAttributeSize + \
									 sizeofObject( \
										sizeofObject( certSize ) ) );

	/* If the new data will fit into the existing storage, we're done */
	if( *newCertDataSize <= pkcs15infoPtr->certDataSize )
		return( CRYPT_OK );

	/* Allocate storage for the new data */
	newCertData = clAlloc( "calculateCertStorage", *newCertDataSize );
	if( newCertData == NULL )
		return( CRYPT_ERROR_MEMORY );
	*newCertDataPtr = newCertData;

	return( CRYPT_OK );
	}

/* Delete the public-key entry for a personality, used when we're replacing
   the pubkey with a certificate */

STDC_NONNULL_ARG( ( 1 ) ) \
static void deletePubKey( INOUT PKCS15_INFO *pkcs15infoPtr )
	{
	assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );

	zeroise( pkcs15infoPtr->pubKeyData, pkcs15infoPtr->pubKeyDataSize );
	clFree( "deletePubKey", pkcs15infoPtr->pubKeyData );
	pkcs15infoPtr->pubKeyData = NULL;
	pkcs15infoPtr->pubKeyDataSize = 0;
	}

/* Replace existing public-key or certificate data with updated 
   information */

STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void replacePubkeyData( INOUT PKCS15_INFO *pkcs15infoPtr, 
							   IN_BUFFER( newPubKeyDataSize ) \
								const void *newPubKeyData, 
							   IN_LENGTH_SHORT_MIN( 16 ) \
								const int newPubKeyDataSize,
							   IN_LENGTH_SHORT const int newPubKeyOffset )
	{
	assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isReadPtr( newPubKeyData, newPubKeyDataSize ) );

	REQUIRES_V( newPubKeyDataSize >= 16 && \
				newPubKeyDataSize < MAX_INTLENGTH_SHORT );
	REQUIRES_V( newPubKeyOffset > 0 && \
				newPubKeyOffset < newPubKeyDataSize && \
				newPubKeyOffset < MAX_INTLENGTH_SHORT );

	/* If we've allocated new storage for the data rather than directly 
	   replacing the existing entry, free the existing entry and replace it 
	   with the new one */
	if( newPubKeyData != pkcs15infoPtr->pubKeyData )
		{
		if( pkcs15infoPtr->pubKeyData != NULL )
			{
			zeroise( pkcs15infoPtr->pubKeyData, 
					 pkcs15infoPtr->pubKeyDataSize );
			clFree( "replacePubkeyData", pkcs15infoPtr->pubKeyData );
			}
		pkcs15infoPtr->pubKeyData = ( void * ) newPubKeyData;
		}

	/* Update the size information */
	pkcs15infoPtr->pubKeyDataSize = newPubKeyDataSize;
	pkcs15infoPtr->pubKeyOffset = newPubKeyOffset;
	}

STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void replaceCertData( INOUT PKCS15_INFO *pkcs15infoPtr, 
							 IN_BUFFER( newCertDataSize ) \
								const void *newCertData, 
							 IN_LENGTH_SHORT_MIN( 16 ) \
								const int newCertDataSize,
							 IN_LENGTH_SHORT const int newCertOffset )
	{
	assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isReadPtr( newCertData, newCertDataSize ) );

	REQUIRES_V( newCertDataSize >= 16 && \
				newCertDataSize < MAX_INTLENGTH_SHORT );
	REQUIRES_V( newCertOffset > 0 && \
				newCertOffset < newCertDataSize && \
				newCertOffset < MAX_INTLENGTH_SHORT );

	/* If we've allocated new storage for the data rather than directly 
	   replacing the existing entry, free the existing entry and replace it 
	   with the new one */
	if( newCertData != pkcs15infoPtr->certData )
		{
		if( pkcs15infoPtr->certData != NULL )
			{
			zeroise( pkcs15infoPtr->certData, pkcs15infoPtr->certDataSize );
			clFree( "replaceCertData", pkcs15infoPtr->certData );
			}
		pkcs15infoPtr->certData = ( void * ) newCertData;
		}

	/* Update the size information */
	pkcs15infoPtr->certDataSize = newCertDataSize;
	pkcs15infoPtr->certOffset = newCertOffset;
	}

/****************************************************************************
*																			*
*								Add a Certificate							*
*																			*
****************************************************************************/

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 6 ) ) \
int pkcs15AddCert( INOUT PKCS15_INFO *pkcs15infoPtr, 
				   IN_HANDLE const CRYPT_CERTIFICATE iCryptCert,
				   IN_BUFFER_OPT( privKeyAttributeSize ) \
					const void *privKeyAttributes, 
				   IN_LENGTH_SHORT_Z const int privKeyAttributeSize,
				   IN_ENUM( CERTADD ) const CERTADD_TYPE certAddType, 
				   INOUT ERROR_INFO *errorInfo )
	{
	MESSAGE_DATA msgData;
	STREAM stream;
	BYTE certAttributes[ KEYATTR_BUFFER_SIZE + 8 ];
	void *newCertData = pkcs15infoPtr->certData;
	void *newPrivKeyData = pkcs15infoPtr->privKeyData;
	int newCertDataSize = DUMMY_INIT, certInfoSize = DUMMY_INIT;
	int newPrivKeyDataSize = DUMMY_INIT, privKeyInfoSize = DUMMY_INIT;
	int newCertOffset = DUMMY_INIT, certAttributeSize;
	int subType = PKCS15_SUBTYPE_NORMAL, keyTypeTag, status;

	assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( ( certAddType == CERTADD_UPDATE_EXISTING && \
			  isReadPtr( privKeyAttributes, privKeyAttributeSize ) ) || \
			( ( certAddType == CERTADD_NORMAL || \
				certAddType == CERTADD_STANDALONE_CERT ) && \
			  privKeyAttributes == NULL && privKeyAttributeSize == 0 ) );

	REQUIRES( isHandleRangeValid( iCryptCert ) );
	REQUIRES( ( certAddType == CERTADD_UPDATE_EXISTING && \
				privKeyAttributes != NULL && \
				privKeyAttributeSize > 0 && \
				privKeyAttributeSize < MAX_INTLENGTH_SHORT ) || \
			  ( ( certAddType == CERTADD_NORMAL || \
				  certAddType == CERTADD_STANDALONE_CERT ) && \
				privKeyAttributes == NULL && privKeyAttributeSize == 0 ) );
	REQUIRES( certAddType > CERTADD_NONE && certAddType < CERTADD_LAST );
	REQUIRES( errorInfo != NULL );

	/* Get the tag for encoding the key data */
	status = getKeyTypeTag( iCryptCert, CRYPT_ALGO_NONE, &keyTypeTag );
	if( cryptStatusError( status ) )
		return( status );

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

		status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE,
								  &value, CRYPT_CERTINFO_TRUSTED_IMPLICIT );
		if( cryptStatusError( status ) || !value )
			{
			retExtArg( CRYPT_ARGERROR_NUM1, 
					   ( CRYPT_ARGERROR_NUM1, errorInfo, 
						 "Only a trusted certificate can be added as a "
						 "standalone certificate" ) );
			}

		/* Set the personality type to certificate-only */
		subType = PKCS15_SUBTYPE_CERT;
		}

	/* Write the certificate attributes */
	status = writeCertAttributes( certAttributes, KEYATTR_BUFFER_SIZE, 
								  &certAttributeSize, pkcs15infoPtr, 
								  iCryptCert );
	if( cryptStatusError( status ) )
		{
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't write certificate attributes" ) );
		}

	/* Find out how big the PKCS #15 data will be and allocate room for it.
	   Since adding the certificate will affect the key attributes we need 
	   to rewrite the key information once we've added the certificate */
	if( certAddType == CERTADD_UPDATE_EXISTING )
		{
		/* Since we're re-using pre-encoded private key data the extra 
		   information is already present in encoded form so we set the 
		   extraDataSize parameter to zero */
		privKeyInfoSize = pkcs15infoPtr->privKeyDataSize - \

⌨️ 快捷键说明

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