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

📄 keyex.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
							  &cryptMode, CRYPT_CTXINFO_MODE );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );

	/* Read the encrypted key record up to the start of the encrypted key and
	   make sure we'll be using the correct type of encryption context to
	   decrypt it */
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	sMemConnect( &stream, encryptedKey, encryptedKeyLength );
	status = readKeyexFunction( &stream, &queryInfo );
	sMemDisconnect( &stream );
	if( cryptStatusOK( status ) && \
		( cryptAlgo != queryInfo.cryptAlgo || \
		  cryptMode != queryInfo.cryptMode ) )
		status = CRYPT_ARGERROR_NUM1;
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}

	/* Extract the encrypted key from the buffer and decrypt it.  Since we 
	   don't want another thread changing the IV while we're using the import
	   context, we lock it for the duration */
	status = krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptStatusError( status ) )
		return( status );
	if( needsIV( cryptMode ) && cryptAlgo != CRYPT_ALGO_RC4 )
		{
		setMessageData( &msgData, queryInfo.iv, queryInfo.ivLength );
		krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE_S, &msgData, 
						 CRYPT_CTXINFO_IV );
		}
	setMechanismWrapInfo( &mechanismInfo, 
						  queryInfo.dataStart, queryInfo.dataLength, 
						  NULL, 0, iSessionKeyContext, iImportContext, 
						  CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT, 
							  &mechanismInfo, MECHANISM_ENC_CMS );
	krnlSendMessage( iImportContext, IMESSAGE_SETATTRIBUTE, 
					 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
	clearMechanismInfo( &mechanismInfo );
	zeroise( &queryInfo, sizeof( QUERY_INFO ) );

	return( status );
	}

/* Import a public-key encrypted session key */

static int importPublicKey( const void *encryptedKey, 
							const int encryptedKeyLength,
							const CRYPT_CONTEXT iSessionKeyContext,
							const CRYPT_CONTEXT iImportContext,
							CRYPT_CONTEXT *iReturnedContext,
							const KEYEX_TYPE keyexType )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	const READKEYTRANS_FUNCTION readKeyexFunction = \
										keytransReadTable[ keyexType ];
	QUERY_INFO queryInfo;
	STREAM stream;
	int status;

	/* Make sure the requested key exchange format is available */
	if( readKeyexFunction == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* Read the encrypted key record up to the start of the encrypted key and
	   make sure we've been given the correct key */
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	sMemConnect( &stream, encryptedKey, encryptedKeyLength );
	status = readKeyexFunction( &stream, &queryInfo );
	sMemDisconnect( &stream );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;
		int compareType;

		setMessageData( &msgData, queryInfo.keyID, 
						queryInfo.keyIDlength );
		switch( keyexType )
			{
			case KEYEX_CMS:
				setMessageData( &msgData, queryInfo.iAndSStart, 
								queryInfo.iAndSLength );
				compareType = MESSAGE_COMPARE_ISSUERANDSERIALNUMBER;
				break;

			case KEYEX_CRYPTLIB:
				compareType = MESSAGE_COMPARE_KEYID;
				break;

			case KEYEX_PGP:
				compareType = ( queryInfo.version == PGP_VERSION_2 ) ? \
							  MESSAGE_COMPARE_KEYID_PGP : \
							  MESSAGE_COMPARE_KEYID_OPENPGP;
				break;

			default:
				assert( NOTREACHED );
				return( CRYPT_ERROR_NOTAVAIL );
			}
		status = krnlSendMessage( iImportContext, IMESSAGE_COMPARE, 
								  &msgData, compareType );
		if( cryptStatusError( status ) && \
			compareType == MESSAGE_COMPARE_KEYID_OPENPGP )
			/* Some broken PGP implementations put PGP 2.x IDs in packets
			   marked as OpenPGP packets, so if we were doing a check for
			   an OpenPGP ID and it failed, fall back to a PGP 2.x one */
			status = krnlSendMessage( iImportContext, IMESSAGE_COMPARE, 
									  &msgData, MESSAGE_COMPARE_KEYID_PGP );
		if( cryptStatusError( status ) )
			/* A failed comparison is reported as a generic CRYPT_ERROR,
			   convert it into a wrong-key error */
			status = CRYPT_ERROR_WRONGKEY;
		}
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}

	/* Decrypt the encrypted key and load it into the context */
	if( keyexType != KEYEX_PGP )
		{
		setMechanismWrapInfo( &mechanismInfo, 
							  queryInfo.dataStart, queryInfo.dataLength, 
							  NULL, 0, iSessionKeyContext, iImportContext, 
							  CRYPT_UNUSED );
		status = krnlSendMessage( iImportContext, IMESSAGE_DEV_IMPORT, 
								  &mechanismInfo, MECHANISM_ENC_PKCS1 );
		}
	else
		{
		/* PGP doesn't provide separate session key information with the 
		   encrypted data but wraps it up alongside the encrypted key, so we
		   can't import the wrapped key into a context via the standard key
		   import functions but instead have to create the context as part 
		   of the unwrap process */
		setMechanismWrapInfo( &mechanismInfo, queryInfo.dataStart, 
							  queryInfo.dataLength, NULL, 0, CRYPT_UNUSED, 
							  iImportContext, CRYPT_UNUSED );
		status = krnlSendMessage( iImportContext, IMESSAGE_DEV_IMPORT, 
								  &mechanismInfo, MECHANISM_ENC_PKCS1_PGP );
		if( cryptStatusOK( status ) )
			*iReturnedContext = mechanismInfo.keyContext;
		}
	clearMechanismInfo( &mechanismInfo );
	zeroise( &queryInfo, sizeof( QUERY_INFO ) );

	return( status );
	}

#if 0	/* 24/11/02 Removed since it was only used for Fortezza */

/* Import a key agreement session key */

static int importKeyAgreeKey( const void *encryptedKey, 
							  const int encryptedKeyLength,
							  const CRYPT_CONTEXT iSessionKeyContext,
							  const CRYPT_CONTEXT iImportContext )
	{
	CRYPT_CONTEXT iLocalContext;
	QUERY_INFO queryInfo;
	STREAM stream;
	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
	int status;

	/* Read the key agreement record.  Due to the somewhat peculiar concept
	   of what constitutes a public key for DH, this doesn't really work as
	   well as the standard key wrap algorithms since what we're reading are
	   the components of a complete context.  As a result the initiator and
	   responder for the DH exchange end up with the following:

							Initiator				Responder

	   cryptInfoPtr			p, g, x(I), y(I)		-

	   iLocalContext		p, g, y(R)				p, g, y(I)

	   If we're doing the import for the responder, we copy the values from
	   the import context into the responder context and perform a key load,
	   which generates the responders x value and key ID.  This is a horrible
	   kludge, what we should be doing is passing the import context back to
	   the user but this isn't possible because cryptImportKey() passes the
	   import context by value.

	   If we're doing the import for the initiator, we just check that the
	   key used by the responder was the same as the one used by the
	   initiator */
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	sMemConnect( &stream, encryptedKey, encryptedKeyLength );
	status = readKeyAgreeInfo( &stream, &queryInfo, &iLocalContext );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	krnlSendNotifier( iLocalContext, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		return( status );

	/* Generate the shared secret value and load it into the session key
	   context.  We use a fixed 64-bit salt and explicitly set the iteration 
	   count to make sure it isn't upset if the user changes config options */
	status = krnlSendMessage( iImportContext, IMESSAGE_CTX_DECRYPT, 
							  buffer, CRYPT_UNUSED );
	if( !cryptStatusError( status ) )
		{
		static const BYTE *salt = ( BYTE * ) "\x00\x00\x00\x00\x00\x00\x00\x00";
		static const int iterations = 100;
		RESOURCE_DATA msgData;

		krnlSendMessage( iSessionKeyContext, IMESSAGE_SETATTRIBUTE, 
						 ( int * ) &iterations, CRYPT_CTXINFO_KEYING_ITERATIONS );
		setMessageData( &msgData, ( void * ) salt, 8 );
		krnlSendMessage( iSessionKeyContext, IMESSAGE_SETATTRIBUTE_S, 
						 &msgData, CRYPT_CTXINFO_KEYING_SALT );
		setMessageData( &msgData, buffer, status );
		status = krnlSendMessage( iSessionKeyContext, IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_KEYING_VALUE );
		}

	return( status );
	}
#endif /* 0 */

/****************************************************************************
*																			*
*							Import/Export a Session Key						*
*																			*
****************************************************************************/

/* Import an extended encrypted key, either a cryptlib key or a CMS key */

static CRYPT_FORMAT_TYPE getFormatType( const void *data )
	{
	STREAM stream;
	const BYTE *dataPtr = data;
#ifdef USE_PGP
	long length;
#endif /* USE_PGP */
	int status;

	/* Figure out what we've got.  PKCS #7/CMS/SMIME keyTrans begins:
		keyTransRecipientInfo ::= SEQUENCE {
			version		INTEGER (0|2),
	   while a kek begins:
		kekRecipientInfo ::= [3] IMPLICIT SEQUENCE {
			version		INTEGER (4),
	   which allows us to determine which type of object we have */
	if( *dataPtr == BER_SEQUENCE )
		{
		CRYPT_FORMAT_TYPE formatType = CRYPT_FORMAT_NONE;

		sMemConnect( &stream, data, 16 );
		status = readSequence( &stream, NULL );
		if( cryptStatusOK( status ) )
			{
			long version;

			if( cryptStatusOK( readShortInteger( &stream, &version ) ) )
				formatType = ( version == 0 ) ? CRYPT_FORMAT_CMS : \
							 ( version == 2 ) ? CRYPT_FORMAT_CRYPTLIB : \
							 CRYPT_FORMAT_NONE;
			}
		sMemDisconnect( &stream );

		return( formatType );
		}
	if( *dataPtr == MAKE_CTAG( 3 ) )
		{
		CRYPT_FORMAT_TYPE formatType = CRYPT_FORMAT_NONE;

		sMemConnect( &stream, data, 16 );
		status = readConstructed( &stream, NULL, 3 );
		if( cryptStatusOK( status ) )
			{
			long version;

			if( cryptStatusOK( readShortInteger( &stream, &version ) ) )
				formatType = ( version == 0 ) ? CRYPT_FORMAT_CRYPTLIB : \
												CRYPT_FORMAT_NONE;
			}
		sMemDisconnect( &stream );

		return( formatType );
		}

#ifdef USE_PGP
	/* It's not ASN.1 data, check for PGP data */
	sMemConnect( &stream, data, 16 );
	status = pgpReadPacketHeader( &stream, NULL, &length );
	if( cryptStatusOK( status ) && length > 30 && length < 8192 )
		{
		sMemDisconnect( &stream );
		return( CRYPT_FORMAT_PGP );
		}
	sMemDisconnect( &stream );
#endif /* USE_PGP */

	return( CRYPT_FORMAT_NONE );
	}

C_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,
						C_IN int encryptedKeyLength,
						C_IN CRYPT_CONTEXT importKey,
						C_IN CRYPT_CONTEXT sessionKeyContext,
						C_OUT CRYPT_CONTEXT C_PTR returnedContext )
	{
	CRYPT_FORMAT_TYPE formatType;
	CRYPT_ALGO_TYPE cryptAlgo;
	CRYPT_CONTEXT iReturnedContext;
	MESSAGE_CHECK_TYPE checkType;
	int owner, originalOwner, status;

	/* Perform basic error checking */
	if( encryptedKeyLength < MIN_CRYPT_OBJECTSIZE )
		return( CRYPT_ERROR_PARAM2 );
	if( !isReadPtr( encryptedKey, encryptedKeyLength ) )
		return( CRYPT_ERROR_PARAM1 );
	if( ( formatType = getFormatType( encryptedKey ) ) == CRYPT_FORMAT_NONE )
		return( CRYPT_ERROR_BADDATA );

	/* Check the importing key */
	status = krnlSendMessage( importKey, MESSAGE_GETATTRIBUTE, 
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM3 : status );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		checkType = ( cryptAlgo == CRYPT_ALGO_DH ) ? \
					MESSAGE_CHECK_PKC_KA_IMPORT : MESSAGE_CHECK_PKC_DECRYPT;
	else
		checkType = MESSAGE_CHECK_CRYPT;
	if( isDlpAlgo( cryptAlgo ) )
		/* The DLP algorithms have specialised data-formatting requirements 
		   and can't normally be directly accessed via external messages, 
		   however if we're performing a key export this is OK since they're
		   being used from cryptlib-internal routines.  Doing the check via
		   an internal message is safe since we've already checked its 
		   external accessibility when we got the algorithm info */
		status = krnlSendMessage( importKey, IMESSAGE_CHECK, NULL, 
								  checkType );
	else
		status = krnlSendMessage( importKey, MESSAGE_CHECK, NULL, 
								  checkType );
	if( cryptAlgo == CRYPT_ALGO_DH && status == CRYPT_ERROR_NOTINITED )
		/* For key agreement keys the fact that there's no key attribute set
		   is OK since the key parameters are read from the exchanged object */
		status = CRYPT_OK;
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM3 : status );

	/* Check the session key */
	if( formatType == CRYPT_FORMAT_PGP )
		{
		/* PGP stores the session key information with the encrypted key 
		   data, so the user can't provide a context */
		if( sessionKeyContext != CRYPT_UNUSED )
			return( CRYPT_ERROR_PARAM4 );
		if( !isWritePtr( returnedContext, sizeof( CRYPT_CONTEXT ) ) )
			return( CRYPT_ERROR_PARAM5 );
		}
	else
		{
		CRYPT_ALGO_TYPE sessionKeyAlgo;

⌨️ 快捷键说明

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