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

📄 keyex_int.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						Internal Key Exchange Routines						*
*						Copyright Peter Gutmann 1993-2007					*
*																			*
****************************************************************************/

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

/****************************************************************************
*																			*
*							Low-level Key Export Functions					*
*																			*
****************************************************************************/

/* Export a conventionally encrypted session key */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int exportConventionalKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \
							void *encryptedKey, 
						   IN_LENGTH const int encryptedKeyMaxLength,
						   OUT_LENGTH_Z int *encryptedKeyLength,
						   IN_HANDLE_OPT const CRYPT_CONTEXT iSessionKeyContext,
						   IN_HANDLE const CRYPT_CONTEXT iExportContext,
						   IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	const WRITEKEK_FUNCTION writeKeyexFunction = getWriteKekFunction( keyexType );
	BYTE buffer[ CRYPT_MAX_KEYSIZE + 16 + 8 ];
	BYTE *bufPtr = ( encryptedKey == NULL ) ? NULL : buffer;
	const int bufSize = ( encryptedKey == NULL ) ? 0 : CRYPT_MAX_KEYSIZE + 16;
	int keySize, ivSize, status;

	assert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
			isWritePtr( encryptedKey, encryptedKeyMaxLength ) );
	assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );

	REQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
			  ( encryptedKey != NULL && \
				encryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \
				encryptedKeyMaxLength < MAX_INTLENGTH ) );
	REQUIRES( ( keyexType == KEYEX_PGP && \
				iSessionKeyContext == CRYPT_UNUSED ) || \
			  ( keyexType != KEYEX_PGP && \
				isHandleRangeValid( iSessionKeyContext ) ) );
	REQUIRES( isHandleRangeValid( iExportContext ) );
	REQUIRES( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );

	/* Clear return value */
	*encryptedKeyLength = 0;

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

#ifdef USE_PGP
	/* PGP doesn't actually wrap up a key but derives the session key
	   directly from the password.  Because of this there isn't any key
	   wrapping to be done so we just write the key derivation parameters
	   and exit */
	if( keyexType == KEYEX_PGP )
		{
		STREAM stream;

		sMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );
		status = writeKeyexFunction( &stream, iExportContext, NULL, 0 );
		if( cryptStatusOK( status ) )
			*encryptedKeyLength = stell( &stream );
		sMemDisconnect( &stream );

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

	/* Get the export parameters */
	status = krnlSendMessage( iSessionKeyContext, IMESSAGE_GETATTRIBUTE,
							  &keySize, CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );
	if( cryptStatusError( krnlSendMessage( iExportContext,
										   IMESSAGE_GETATTRIBUTE, &ivSize,
										   CRYPT_CTXINFO_IVSIZE ) ) )
		ivSize = 0;

	/* Load an IV into the exporting context.  This is somewhat nasty in that
	   a side-effect of exporting a key is to load an IV, which isn't really 
	   part of the function's job description.  The alternative would be to 
	   require the user to explicitly load an IV before exporting the key, 
	   but this is equally nasty because they'll never remember.  The lesser 
	   of the two evils is to load the IV here and assume that anyone 
	   loading the IV themselves will read the docs, which warn about the 
	   side-effects of exporting a key.

	   Note that we always load a new IV when we export a key because the
	   caller may be using the context to exchange multiple keys.  Since each
	   exported key requires its own IV we perform an unconditional reload.
	   In addition because we don't want another thread coming along and
	   changing the IV while we're in the process of encrypting with it, we
	   lock the exporting key object until the encryption has completed and
	   the IV is written to the output */
	status = krnlSendMessage( iExportContext, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptStatusError( status ) )
		return( status );
	if( ivSize > 0 )
		{
		status = krnlSendNotifier( iExportContext, IMESSAGE_CTX_GENIV );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Encrypt the session key and write the result to the output stream */
	setMechanismWrapInfo( &mechanismInfo, bufPtr, bufSize, NULL, 0, 
						  iSessionKeyContext, iExportContext );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,
							  &mechanismInfo, MECHANISM_ENC_CMS );
	if( cryptStatusOK( status ) )
		{
		STREAM stream;

		/* If we're perfoming a dummy export for a length check, set up a 
		   dummy value to write */
		if( encryptedKey == NULL )
			memset( buffer, 0x01, mechanismInfo.wrappedDataLength );

		sMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );
		status = writeKeyexFunction( &stream, iExportContext,
									 ( encryptedKey != NULL ) ? \
										mechanismInfo.wrappedData : buffer,
									 mechanismInfo.wrappedDataLength );
		if( cryptStatusOK( status ) )
			*encryptedKeyLength = stell( &stream );
		sMemDisconnect( &stream );
		}
	( void ) krnlSendMessage( iExportContext, IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
	clearMechanismInfo( &mechanismInfo );
	zeroise( buffer, CRYPT_MAX_KEYSIZE + 16 );
	return( status );
	}

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int exportPublicKey( OUT_BUFFER_OPT( encryptedKeyMaxLength, *encryptedKeyLength ) \
						void *encryptedKey, 
					 IN_LENGTH const int encryptedKeyMaxLength,
					 OUT_LENGTH_Z int *encryptedKeyLength,
					 IN_HANDLE const CRYPT_CONTEXT iSessionKeyContext,
					 IN_HANDLE const CRYPT_CONTEXT iExportContext,
					 IN_BUFFER_OPT( auxInfoLength ) const void *auxInfo, 
					 IN_LENGTH_SHORT_Z const int auxInfoLength,
					 IN_ENUM( KEYEX ) const KEYEX_TYPE keyexType )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	const WRITEKEYTRANS_FUNCTION writeKetransFunction = getWriteKeytransFunction( keyexType );
	BYTE buffer[ MAX_PKCENCRYPTED_SIZE + 8 ];
	BYTE *bufPtr = ( encryptedKey == NULL ) ? NULL : buffer;
	const int bufSize = ( encryptedKey == NULL ) ? 0 : MAX_PKCENCRYPTED_SIZE;
	int keySize, status;

	assert( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
			isWritePtr( encryptedKey, encryptedKeyMaxLength ) );
	assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );
	assert( ( auxInfo == NULL && auxInfoLength == 0 ) || \
			isReadPtr( auxInfo, auxInfoLength ) );
	
	REQUIRES( ( encryptedKey == NULL && encryptedKeyMaxLength == 0 ) || \
			  ( encryptedKey != NULL && \
				encryptedKeyMaxLength > MIN_CRYPT_OBJECTSIZE && \
				encryptedKeyMaxLength < MAX_INTLENGTH ) );
	REQUIRES( isHandleRangeValid( iSessionKeyContext ) );
	REQUIRES( isHandleRangeValid( iExportContext ) );
	REQUIRES( ( auxInfo == NULL && auxInfoLength == 0 ) || \
			  ( auxInfo != NULL && \
				auxInfoLength > 0 && auxInfoLength < MAX_INTLENGTH_SHORT ) );
	REQUIRES( keyexType > KEYEX_NONE && keyexType < KEYEX_LAST );

	/* Clear return value */
	*encryptedKeyLength = 0;

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

	/* Get the export parameters */
	status = krnlSendMessage( iSessionKeyContext, IMESSAGE_GETATTRIBUTE,
							  &keySize, CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );

	/* Encrypt the session key and write the result to the output stream */
	setMechanismWrapInfo( &mechanismInfo, bufPtr, bufSize, NULL, 0, 
						  iSessionKeyContext, iExportContext );
	status = krnlSendMessage( iExportContext, IMESSAGE_DEV_EXPORT,
							  &mechanismInfo, ( keyexType == KEYEX_PGP ) ? \
								MECHANISM_ENC_PKCS1_PGP : \
								MECHANISM_ENC_PKCS1 );
	if( cryptStatusOK( status ) )
		{
		STREAM stream;

		/* If we're perfoming a dummy export for a length check, set up a 
		   dummy value to write */
		if( encryptedKey == NULL )
			memset( buffer, 0x01, mechanismInfo.wrappedDataLength );

		sMemOpenOpt( &stream, encryptedKey, encryptedKeyMaxLength );
		status = writeKetransFunction ( &stream, iExportContext,
										( encryptedKey != NULL ) ? \
											mechanismInfo.wrappedData : buffer,
										mechanismInfo.wrappedDataLength,
										auxInfo, auxInfoLength );
		if( cryptStatusOK( status ) )
			*encryptedKeyLength = stell( &stream );
		sMemDisconnect( &stream );
		}
	clearMechanismInfo( &mechanismInfo );

	/* Clean up */
	zeroise( buffer, MAX_PKCENCRYPTED_SIZE );
	return( status );

⌨️ 快捷键说明

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