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

📄 keyex.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 3 页
字号:
			status = importPublicKey( encryptedKey, encryptedKeyLength,
									  CRYPT_UNUSED, importKey, 
									  &iReturnedContext, KEYEX_PGP );
			if( cryptStatusOK( status ) )
				/* Make the newly-created context externally visible */
				krnlSendMessage( iReturnedContext, IMESSAGE_SETATTRIBUTE,
								 MESSAGE_VALUE_FALSE, 
								 CRYPT_IATTRIBUTE_INTERNAL );
			}
		else
			status = importPublicKey( encryptedKey, encryptedKeyLength,
									  sessionKeyContext, importKey, NULL,
									  ( formatType == CRYPT_FORMAT_CMS ) ? \
										KEYEX_CMS : KEYEX_CRYPTLIB );
		}
	else
		status = importConventionalKey( encryptedKey, encryptedKeyLength,
							sessionKeyContext, importKey,
							( formatType == CRYPT_FORMAT_CRYPTLIB ) ? \
								KEYEX_CRYPTLIB : KEYEX_PGP );

	/* If the import failed, return the session key context to its
	   original owner */
	if( cryptStatusError( status ) )
		{
		if( originalOwner != CRYPT_ERROR )
			krnlSendMessage( sessionKeyContext, MESSAGE_SETATTRIBUTE,
							 &originalOwner, CRYPT_PROPERTY_OWNER );
		}
	else
		/* If we created the session key as part of the import operation,
		   return it to the caller */
		if( formatType == CRYPT_FORMAT_PGP )
			*returnedContext = iReturnedContext;

	if( cryptArgError( status ) )
		/* If we get an argument error from the lower-level code, map the
		   parameter number to the function argument number */
		status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
				 CRYPT_ERROR_PARAM3 : CRYPT_ERROR_PARAM2;
	return( status );
	}

C_RET cryptImportKey( C_IN void C_PTR encryptedKey,
					  C_IN CRYPT_CONTEXT importKey,
					  C_IN CRYPT_CONTEXT sessionKeyContext )
	{
	return( cryptImportKeyEx( encryptedKey, importKey, sessionKeyContext, 
							  NULL ) );
	}

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

C_RET cryptExportKeyEx( C_OUT void C_PTR encryptedKey, 
						C_OUT int C_PTR encryptedKeyLength,
						C_IN CRYPT_FORMAT_TYPE formatType,
						C_IN CRYPT_HANDLE exportKey,
						C_IN CRYPT_CONTEXT sessionKeyContext )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	CRYPT_MODE_TYPE sessionKeyMode;
	const KEYEX_TYPE keyexType = \
			( formatType == CRYPT_FORMAT_AUTO || \
			  formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
			( formatType == CRYPT_FORMAT_PGP ) ? KEYEX_PGP : KEYEX_CMS;
	DYNBUF auxDB;
	MESSAGE_CHECK_TYPE checkType;
	int status;

	/* Perform basic error checking */
	if( encryptedKey != NULL )
		{
		if( checkBadPtrWrite( encryptedKey, MIN_CRYPT_OBJECTSIZE ) )
			return( CRYPT_ERROR_PARAM1 );
		memset( encryptedKey, 0, MIN_CRYPT_OBJECTSIZE );
		}
	if( checkBadPtrWrite( encryptedKeyLength, sizeof( int ) ) )
		return( CRYPT_ERROR_PARAM2 );
	*encryptedKeyLength = 0;
	if( formatType <= CRYPT_FORMAT_NONE || \
		formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
		return( CRYPT_ERROR_PARAM3 );

	/* Check the exporting key */
	status = krnlSendMessage( exportKey, MESSAGE_GETATTRIBUTE, &cryptAlgo, 
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM4 : status );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		checkType = ( cryptAlgo == CRYPT_ALGO_DH ) ? \
					MESSAGE_CHECK_PKC_KA_EXPORT : MESSAGE_CHECK_PKC_ENCRYPT;
	else
		checkType = MESSAGE_CHECK_CRYPT;
	status = krnlSendMessage( exportKey, MESSAGE_CHECK, NULL, checkType );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM4 : status );
	if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
		cryptStatusError( sizeofAlgoIDex( cryptAlgo,
								( CRYPT_ALGO_TYPE ) CRYPT_MODE_CBC, 0 ) ) )
		/* Conventional key wrap requires the use of an CBC mode for the 
		   wrapping (which also implies the use of a block cipher).  CBC mode
		   isn't essential but it's a good safety check, the use of a block 
		   cipher is essential */
		return( CRYPT_ERROR_PARAM4 );

	/* Check the exported key */
	status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE,
							  &sessionKeyMode, CRYPT_CTXINFO_MODE );
	if( status == CRYPT_ARGERROR_VALUE )
		{
		/* No encryption mode attribute present, it has to be a MAC 
		   context */
		checkType = MESSAGE_CHECK_MAC;
		status = CRYPT_OK;
		}
	else
		checkType = MESSAGE_CHECK_CRYPT;
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( sessionKeyContext, MESSAGE_CHECK, NULL, 
								  checkType );
#ifdef USE_PGP
	if( formatType == CRYPT_FORMAT_PGP )
		{
		CRYPT_ALGO_TYPE sessionKeyAlgo;

		/* PGP can only handle a limited subset of algorithms, make sure this
		   is an algorithm type which can be represented in the PGP format */
		status = krnlSendMessage( sessionKeyContext, MESSAGE_GETATTRIBUTE, 
								  &sessionKeyAlgo, CRYPT_CTXINFO_ALGO );
		if( cryptStatusError( status ) )
			return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
					CRYPT_ERROR_PARAM5 : status );
		if( cryptStatusError( cryptlibToPgpAlgo( sessionKeyAlgo ) ) )
			return( CRYPT_ERROR_PARAM5 );
		}
#endif /* USE_PGP */
	if( cryptAlgo == CRYPT_ALGO_DH )
		{
		/* If we're using a key agreement algorithm it doesn't matter if the
		   session key context has a key attribute present or not, but the 
		   format has to be cryptlib */
		if( status == CRYPT_ERROR_NOTINITED )
			status = CRYPT_OK;
		if( formatType == CRYPT_FORMAT_CMS || \
			formatType == CRYPT_FORMAT_SMIME )
			status = CRYPT_ERROR_PARAM3;
		}
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM5 : status );

	/* If we're exporting a key in CMS format using a public key we need to
	   obtain recipient information */
	if( ( formatType == CRYPT_FORMAT_CMS || \
		  formatType == CRYPT_FORMAT_SMIME ) && 
		( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
		  cryptAlgo <= CRYPT_ALGO_LAST_PKC ) )
		{
		status = dynCreate( &auxDB, exportKey, 
							( cryptAlgo == CRYPT_ALGO_DH || \
							  cryptAlgo == CRYPT_ALGO_KEA ) ? \
								CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
								CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( cryptStatusError( status ) )
			return( CRYPT_ERROR_PARAM4 );
		}
	else
		dynCreate( &auxDB, CRYPT_UNUSED, CRYPT_UNUSED );

	/* Export it as appropriate */
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		status = exportPublicKey( encryptedKey, encryptedKeyLength,
								  ( encryptedKey == NULL ) ? \
										0 : STREAMSIZE_UNKNOWN,
								  sessionKeyContext, exportKey, 
								  dynData( auxDB ), dynLength( auxDB ), 
								  keyexType );
	else
		status = exportConventionalKey( encryptedKey, encryptedKeyLength,
										( encryptedKey == NULL ) ? \
											0 : STREAMSIZE_UNKNOWN,
										sessionKeyContext, exportKey,
										keyexType );

	/* Clean up */
	dynDestroy( &auxDB );
	if( cryptArgError( status ) )
		/* If we get an argument error from the lower-level code, map the
		   parameter number to the function argument number */
		status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
				 CRYPT_ERROR_PARAM5 : CRYPT_ERROR_PARAM4;
	return( status );
	}

C_RET cryptExportKey( C_OUT void C_PTR encryptedKey, 
					  C_OUT int C_PTR encryptedKeyLength,
					  C_IN CRYPT_HANDLE exportKey,
					  C_IN CRYPT_CONTEXT sessionKeyContext )
	{
	int status;

	status = cryptExportKeyEx( encryptedKey, encryptedKeyLength, 
							   CRYPT_FORMAT_CRYPTLIB, exportKey, 
							   sessionKeyContext );
	return( ( status == CRYPT_ERROR_PARAM4 ) ? CRYPT_ERROR_PARAM3 : \
			( status == CRYPT_ERROR_PARAM5 ) ? CRYPT_ERROR_PARAM4 : status );
	}

/****************************************************************************
*																			*
*						Internal Import/Export Functions					*
*																			*
****************************************************************************/

/* Internal versions of the above.  These skip a lot of the checking done by
   the external versions since they're only called by cryptlib internal
   functions which have already checked the parameters for validity */

int iCryptImportKeyEx( const void *encryptedKey, const int encryptedKeyLength,
					   const CRYPT_FORMAT_TYPE formatType,
					   const CRYPT_CONTEXT iImportKey,
					   const CRYPT_CONTEXT iSessionKeyContext,
					   CRYPT_CONTEXT *iReturnedContext )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	const KEYEX_TYPE keyexType = \
			( formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
			( formatType == CRYPT_FORMAT_CMS || \
			  formatType == CRYPT_FORMAT_SMIME ) ? KEYEX_CMS : KEYEX_PGP;
	int status;

	assert( isReadPtr( encryptedKey, encryptedKeyLength ) );
	assert( formatType > CRYPT_FORMAT_NONE && \
			formatType < CRYPT_FORMAT_LAST );
	assert( checkHandleRange( iImportKey ) );
	assert( ( formatType == CRYPT_FORMAT_PGP && \
			  iSessionKeyContext == CRYPT_UNUSED ) || \
			( formatType != CRYPT_FORMAT_PGP && \
			  checkHandleRange( iSessionKeyContext ) ) );
	assert( ( formatType == CRYPT_FORMAT_PGP && \
			  iReturnedContext != NULL ) || \
			( formatType != CRYPT_FORMAT_PGP && \
			  iReturnedContext == NULL ) );

	/* Import it as appropriate.  We don't handle key agreement at this
	   level */
	status = krnlSendMessage( iImportKey, IMESSAGE_GETATTRIBUTE, &cryptAlgo, 
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
		cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
		return( importConventionalKey( encryptedKey, encryptedKeyLength,
									   iSessionKeyContext, iImportKey, 
									   keyexType ) );
	return( importPublicKey( encryptedKey, encryptedKeyLength,
							 iSessionKeyContext, iImportKey, 
							 iReturnedContext, keyexType ) );
	}

int iCryptExportKeyEx( void *encryptedKey, int *encryptedKeyLength,
					   const int encryptedKeyMaxLength,
					   const CRYPT_FORMAT_TYPE formatType,
					   const CRYPT_CONTEXT iSessionKeyContext,
					   const CRYPT_CONTEXT iExportKey,
					   const CRYPT_CONTEXT iAuxContext )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	const KEYEX_TYPE keyexType = \
			( formatType == CRYPT_FORMAT_CRYPTLIB ) ? KEYEX_CRYPTLIB : \
			( formatType == CRYPT_FORMAT_CMS || \
			  formatType == CRYPT_FORMAT_SMIME ) ? KEYEX_CMS : KEYEX_PGP;
	DYNBUF auxDB;
	int status;

	assert( encryptedKey == NULL || \
			isWritePtr( encryptedKey, MIN_CRYPT_OBJECTSIZE ) );
	assert( isWritePtr( encryptedKeyLength, sizeof( int ) ) );
	assert( formatType > CRYPT_FORMAT_NONE && \
			formatType < CRYPT_FORMAT_LAST );
	assert( checkHandleRange( iExportKey ) );

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

	/* Perform simplified error checking */
	status = krnlSendMessage( iExportKey, IMESSAGE_GETATTRIBUTE, &cryptAlgo, 
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );

	/* If we're exporting a key in CMS format using a public key we need to
	   obtain recipient information */
	if( ( formatType == CRYPT_FORMAT_CMS || \
		  formatType == CRYPT_FORMAT_SMIME ) && \
		( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
		  cryptAlgo <= CRYPT_ALGO_LAST_PKC ) )
		{
		status = dynCreate( &auxDB, iExportKey, 
							( cryptAlgo == CRYPT_ALGO_DH || \
							  cryptAlgo == CRYPT_ALGO_KEA ) ? \
								CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER : \
								CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( cryptStatusError( status ) )
			return( CRYPT_ERROR_PARAM4 );
		}
	else
		dynCreate( &auxDB, CRYPT_UNUSED, CRYPT_UNUSED );

	/* Export it as appropriate */
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		status = exportPublicKey( encryptedKey, encryptedKeyLength,
								  encryptedKeyMaxLength, iSessionKeyContext, 
								  iExportKey, dynData( auxDB ), 
								  dynLength( auxDB ), keyexType );
	else
		status = exportConventionalKey( encryptedKey, encryptedKeyLength,
										encryptedKeyMaxLength, 
										iSessionKeyContext, iExportKey,
										keyexType );

	/* Clean up */
	dynDestroy( &auxDB );
	return( status );
	}

/****************************************************************************
*																			*
*								Object Query Function						*
*																			*
****************************************************************************/

/* Query an object.  This is just a wrapper which provides an external
   interface for the lower-level object-query routines */

C_RET cryptQueryObject( C_IN void C_PTR objectData,
						C_OUT CRYPT_OBJECT_INFO C_PTR cryptObjectInfo )
	{
	QUERY_INFO queryInfo;
	STREAM stream;
	int value, status;

	/* Perform basic error checking and clear the return value */
	if( checkBadPtrRead( objectData, MIN_CRYPT_OBJECTSIZE ) )
		return( CRYPT_ERROR_PARAM1 );
	if( checkBadPtrWrite( cryptObjectInfo, sizeof( CRYPT_OBJECT_INFO ) ) )
		return( CRYPT_ERROR_PARAM2 );
	memset( cryptObjectInfo, 0, sizeof( CRYPT_OBJECT_INFO ) );

	/* Query the object.  This is just a wrapper for the lower-level object-
	   query functions.  The length should be specified as a user parameter, 
	   unfortunately the early cryptlib API didn't take length parameters 
	   when it wasn't absolutely necessary so we have to take a guess at a 
	   safe size limit and hope that the data isn't all done with an 
	   indefinite encoding */
	sMemConnect( &stream, ( void * ) objectData, 2048 );
	value = *( ( BYTE * ) objectData );
	if( value == BER_SEQUENCE || value == MAKE_CTAG( 3 ) )
		status = queryAsn1Object( &stream, &queryInfo );
#ifdef USE_PGP
	else
		status = queryPgpObject( &stream, &queryInfo );
#endif /* USE_PGP */
	sMemDisconnect( &stream );

	/* Copy the externally-visible fields across */
	if( cryptStatusOK( status ) )
		{
		cryptObjectInfo->objectType = queryInfo.type;
		cryptObjectInfo->cryptAlgo = queryInfo.cryptAlgo;
		cryptObjectInfo->cryptMode = queryInfo.cryptMode;
		if( queryInfo.type == CRYPT_OBJECT_SIGNATURE )
			cryptObjectInfo->hashAlgo = queryInfo.hashAlgo;
		if( queryInfo.type == CRYPT_OBJECT_ENCRYPTED_KEY && \
			queryInfo.saltLength )
			{
			memcpy( cryptObjectInfo->salt, queryInfo.salt, 
					queryInfo.saltLength );
			cryptObjectInfo->saltSize = queryInfo.saltLength;
			}
		}

	return( status );
	}

⌨️ 快捷键说明

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