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

📄 pkcs15_adpr.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
			status = sSkip( stream, exportedKeySize );
		}

	/* Clean up */
	krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Write the private key wrapped using the session key */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int writeWrappedPrivateKey( OUT_BUFFER( wrappedKeyMaxLength, \
											  *wrappedKeyLength ) 
									void *wrappedKey, 
								   IN_LENGTH_SHORT_MIN( 16 ) \
									const int wrappedKeyMaxLength,
								   OUT_LENGTH_SHORT_Z int *wrappedKeyLength,
								   IN_HANDLE const CRYPT_HANDLE iPrivKeyContext,
								   IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,
								   IN_ALGO const CRYPT_ALGO_TYPE pkcAlgo )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	STREAM encDataStream;
	int length = DUMMY_INIT, status;

	assert( isWritePtr( wrappedKey, wrappedKeyMaxLength ) );
	assert( isWritePtr( wrappedKeyLength, sizeof( int ) ) );

	REQUIRES( wrappedKeyMaxLength >= 16 && \
			  wrappedKeyMaxLength < MAX_INTLENGTH_SHORT );
	REQUIRES( isHandleRangeValid( iPrivKeyContext ) );
	REQUIRES( isHandleRangeValid( iSessionKeyContext ) );
	REQUIRES( pkcAlgo >= CRYPT_ALGO_FIRST_PKC && \
			  pkcAlgo <= CRYPT_ALGO_LAST_PKC );

	/* Clear return values */
	memset( wrappedKey, 0, min( 16, wrappedKeyMaxLength ) );
	*wrappedKeyLength = 0;

	/* Export the wrapped private key */
	setMechanismWrapInfo( &mechanismInfo, wrappedKey, wrappedKeyMaxLength, 
						  NULL, 0, iPrivKeyContext, iSessionKeyContext );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
	if( cryptStatusOK( status ) )
		length = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusError( status ) )
		return( status );
	*wrappedKeyLength = length;

	/* Try and check that the wrapped key data no longer contains 
	   identifiable structured data.  We can only do this for RSA keys 
	   because the amount of information present for DLP keys (a single 
	   short integer) is too small to reliably check.  This check is 
	   performed in addition to checks already performed by the encryption 
	   code and the key wrap code */
	if( pkcAlgo != CRYPT_ALGO_RSA )
		return( CRYPT_OK );

	/* For RSA keys the data would be:

		SEQUENCE {
			[3] INTEGER,
			...
			}

	   99.9% of all wrapped keys will fail the initial valid-SEQUENCE check 
	   so we provide an early-out for it */
	sMemConnect( &encDataStream, wrappedKey, *wrappedKeyLength );
	status = readSequence( &encDataStream, &length );
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &encDataStream );
		return( CRYPT_OK );
		}

	/* The data must contain at least p and q, or at most all key 
	   components */
	if( length < MIN_PKCSIZE * 2 || length > MAX_PRIVATE_KEYSIZE )
		{
		sMemDisconnect( &encDataStream );
		return( CRYPT_OK );
		}

	/* The first key component is p, encoded as '[3] INTEGER' */
	status = readIntegerTag( &encDataStream, NULL, CRYPT_MAX_PKCSIZE, 
							 &length, 3 );
	if( cryptStatusOK( status ) && \
		( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE ) )
		status = CRYPT_ERROR;
	sMemDisconnect( &encDataStream );
	if( cryptStatusError( status ) )
		return( CRYPT_OK );

	/* We appear to have plaintext data still present in the buffer, clear 
	   it and warn the user */
	zeroise( wrappedKey, wrappedKeyMaxLength );
	assert( DEBUG_WARN );
	return( CRYPT_ERROR_FAILED );
	}

/****************************************************************************
*																			*
*								Add a Private Key							*
*																			*
****************************************************************************/

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 6, 10 ) ) \
int pkcs15AddPrivateKey( INOUT PKCS15_INFO *pkcs15infoPtr, 
						 IN_HANDLE const CRYPT_HANDLE iCryptContext,
						 IN_HANDLE const CRYPT_HANDLE iCryptOwner,
						 IN_BUFFER( passwordLength ) const char *password, 
						 IN_LENGTH_NAME const int passwordLength,
						 IN_BUFFER( privKeyAttributeSize ) \
							const void *privKeyAttributes, 
						 IN_LENGTH_SHORT const int privKeyAttributeSize,
						 IN_ALGO const CRYPT_ALGO_TYPE pkcCryptAlgo, 
						 IN_LENGTH_PKC const int modulusSize, 
						 INOUT ERROR_INFO *errorInfo )
	{
	CRYPT_CONTEXT iSessionKeyContext;
	MECHANISM_WRAP_INFO mechanismInfo;
	STREAM stream;
	BYTE envelopeHeaderBuffer[ 256 + 8 ];
	void *newPrivKeyData = pkcs15infoPtr->privKeyData;
	int newPrivKeyDataSize, newPrivKeyOffset = DUMMY_INIT;
	int privKeySize = DUMMY_INIT, extraDataSize = 0;
	int envelopeHeaderSize, envelopeContentSize, keyTypeTag, status;

	assert( isWritePtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isReadPtr( password, passwordLength ) );
	assert( isReadPtr( privKeyAttributes, privKeyAttributeSize ) );

	REQUIRES( isHandleRangeValid( iCryptContext ) );
	REQUIRES( iCryptOwner == DEFAULTUSER_OBJECT_HANDLE || \
			  isHandleRangeValid( iCryptOwner ) );
	REQUIRES( passwordLength >= MIN_NAME_LENGTH && \
			  passwordLength < MAX_ATTRIBUTE_SIZE );
	REQUIRES( privKeyAttributeSize > 0 && \
			  privKeyAttributeSize < MAX_INTLENGTH_SHORT );
	REQUIRES( pkcCryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
			  pkcCryptAlgo <= CRYPT_ALGO_LAST_PKC );
	REQUIRES( modulusSize >= MIN_PKCSIZE && \
			  modulusSize <= CRYPT_MAX_PKCSIZE );
	REQUIRES( errorInfo != NULL );

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

	/* Create a session key context and generate a key and IV into it.  The 
	   IV would be generated automatically later on when we encrypt data for 
	   the first time but we do it explicitly here to catch any possible 
	   errors at a point where recovery is easier */
	status = createStrongEncryptionContext( &iSessionKeyContext, iCryptOwner );
	if( cryptStatusError( status ) )
		return( status );
	status = krnlSendNotifier( iSessionKeyContext, IMESSAGE_CTX_GENKEY );
	if( cryptStatusOK( status ) )
		status = krnlSendNotifier( iSessionKeyContext, IMESSAGE_CTX_GENIV );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't create session key to wrap private key" ) );
		}

	/* Calculate the eventual encrypted key size */
	setMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, iCryptContext,
						  iSessionKeyContext );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
	if( cryptStatusOK( status ) )
		privKeySize = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	ENSURES( privKeySize <= 256 + MAX_PRIVATE_KEYSIZE );

	/* Write the CMS envelope header for the wrapped private key except for 
	   the outermost wrapper, which we have to defer writing until later 
	   since we won't know the wrapped session key or inner CMS header size 
	   until we've written them.  Since we're using KEKRecipientInfo we use 
	   a version of 2 rather than 0 */
	sMemOpen( &stream, envelopeHeaderBuffer, 256 );
	writeShortInteger( &stream, 2, DEFAULT_TAG );
	status = writeWrappedSessionKey( &stream, iSessionKeyContext,
									 iCryptOwner, password, passwordLength );
	if( cryptStatusOK( status ) )
		status = writeCMSencrHeader( &stream, OID_CMS_DATA, 
									 sizeofOID( OID_CMS_DATA ), privKeySize,
									 iSessionKeyContext );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't write envelope header for wrapping private "
				  "key" ) );
		}
	envelopeHeaderSize = stell( &stream );
	envelopeContentSize = envelopeHeaderSize + privKeySize;
	sMemDisconnect( &stream );

	/* Since we haven't been able to write the outer CMS envelope wrapper 
	   yet we need to adjust the overall size for the additional level of
	   encapsulation */
	privKeySize = ( int ) sizeofObject( privKeySize + envelopeHeaderSize );

	/* Calculate the private-key storage size */
	if( pkcCryptAlgo == CRYPT_ALGO_RSA )
		{
		/* RSA keys have an extra element for PKCS #11 compatibility */
		extraDataSize = sizeofShortInteger( modulusSize );
		}
	status = calculatePrivkeyStorage( pkcs15infoPtr, &newPrivKeyData,
									  &newPrivKeyDataSize, privKeySize, 
									  privKeyAttributeSize, 
									  extraDataSize );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	sMemOpen( &stream, newPrivKeyData, newPrivKeyDataSize );

	/* Write the outer header and attributes */
	writeConstructed( &stream, privKeyAttributeSize + \
							   sizeofObject( sizeofObject( privKeySize ) + \
											 extraDataSize ),
					  keyTypeTag );
	swrite( &stream, privKeyAttributes, privKeyAttributeSize );
	writeConstructed( &stream, sizeofObject( privKeySize + extraDataSize ), 
					  CTAG_OB_TYPEATTR );
	status = writeSequence( &stream, privKeySize + extraDataSize );
	if( cryptStatusOK( status ) )
		newPrivKeyOffset = stell( &stream );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
		if( newPrivKeyData != pkcs15infoPtr->privKeyData )
			clFree( "addPrivateKey", newPrivKeyData );
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't write private key attributes" ) );
		}

	/* Write the previously-encoded CMS envelope header and key exchange
	   information and follow it with the encrypted private key.  Since we
	   now know the size of the envelope header (which we couldn't write
	   earlier) we can add this now too */
	writeConstructed( &stream, envelopeContentSize, CTAG_OV_DIRECTPROTECTED );
	status = swrite( &stream, envelopeHeaderBuffer, envelopeHeaderSize );
	if( cryptStatusOK( status ) )
		{
		void *dataPtr;
		int length;

		status = sMemGetDataBlockRemaining( &stream, &dataPtr, &length );
		if( cryptStatusOK( status ) )
			status = writeWrappedPrivateKey( dataPtr, length, &privKeySize, 
											 iCryptContext, iSessionKeyContext, 
											 pkcCryptAlgo );
		}
	if( cryptStatusOK( status ) )
		status = sSkip( &stream, privKeySize );
	if( cryptStatusOK( status ) && pkcCryptAlgo == CRYPT_ALGO_RSA )
		{
		/* RSA keys have an extra element for PKCS #11 compability that we
		   need to kludge onto the end of the private-key data */
		status = writeShortInteger( &stream, modulusSize, DEFAULT_TAG );
		}
	krnlSendNotifier( iSessionKeyContext, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't wrap private key using session key" ) );
		}
	assert( newPrivKeyDataSize == stell( &stream ) );
	sMemDisconnect( &stream );
	ENSURES( !cryptStatusError( checkObjectEncoding( newPrivKeyData, \
													 newPrivKeyDataSize ) ) );

	/* Replace the old data with the newly-written data */
	replacePrivkeyData( pkcs15infoPtr, newPrivKeyData, 
						newPrivKeyDataSize, newPrivKeyOffset );
	return( CRYPT_OK );
	}
#endif /* USE_PKCS15 */

⌨️ 快捷键说明

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