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

📄 lib_keyx.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	   context, we lock it for the duration */
	krnlSendNotifier( iImportContext, RESOURCE_IMESSAGE_LOCK );
	if( needsIV( cryptMode ) && cryptAlgo != CRYPT_ALGO_RC4 )
		{
		setResourceData( &msgData, queryInfo.iv, queryInfo.ivLength );
		krnlSendMessage( iImportContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S, 
						 &msgData, CRYPT_CTXINFO_IV );
		}
	setMechanismWrapInfo( &mechanismInfo, 
						  queryInfo.dataStart, queryInfo.dataLength, 
						  NULL, 0, iSessionKeyContext, iImportContext, 
						  CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_IMPORT, &mechanismInfo, 
							  MECHANISM_CMS );
	krnlSendNotifier( iImportContext, RESOURCE_IMESSAGE_UNLOCK );
	clearMechanismInfo( &mechanismInfo );

	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 )
	{
	MECHANISM_WRAP_INFO mechanismInfo;
	QUERY_INFO queryInfo;
	RESOURCE_DATA msgData;
	STREAM stream;
	int status;

	/* Read the encrypted key record up to the start of the encrypted key and
	   make sure we've been given the correct key */
	sMemConnect( &stream, encryptedKey, encryptedKeyLength );
	status = readKeyTransInfo( &stream, &queryInfo );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	if( queryInfo.formatType == CRYPT_FORMAT_CMS )
		{
		setResourceData( &msgData, queryInfo.iAndSStart, queryInfo.iAndSLength );
		if( krnlSendMessage( iImportContext, RESOURCE_IMESSAGE_COMPARE, &msgData,
				RESOURCE_MESSAGE_COMPARE_ISSUERANDSERIALNUMBER ) != CRYPT_OK )
			status = CRYPT_ERROR_WRONGKEY;
		}
	else
		{
		setResourceData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );
		if( krnlSendMessage( iImportContext, RESOURCE_IMESSAGE_COMPARE,
					&msgData, RESOURCE_MESSAGE_COMPARE_KEYID ) != CRYPT_OK )
			status = CRYPT_ERROR_WRONGKEY;
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Decrypt the encrypted key and load it into the context */
	setMechanismWrapInfo( &mechanismInfo, 
						  queryInfo.dataStart, queryInfo.dataLength, 
						  NULL, 0, iSessionKeyContext, iImportContext, 
						  CRYPT_UNUSED );
	status = krnlSendMessage( iImportContext, RESOURCE_IMESSAGE_DEV_IMPORT, 
							  &mechanismInfo, MECHANISM_PKCS1 );
	clearMechanismInfo( &mechanismInfo );

	return( status );
	}

/* Import a key agreement session key */

static int importKeyAgreeKey( const void *encryptedKey, 
							  const CRYPT_CONTEXT iSessionKeyContext,
							  const CRYPT_CONTEXT iImportContext )
	{
	CRYPT_CONTEXT iLocalContext;
	QUERY_INFO queryInfo;
	STREAM stream;
	BYTE buffer[ CRYPT_MAX_PKCSIZE ];
	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 */
	sMemConnect( &stream, encryptedKey, STREAMSIZE_UNKNOWN );
	status = readKeyAgreeInfo( &stream, &queryInfo, &iLocalContext );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
#if 0
	getCheckInternalResource( iImportContext, cryptInfoPtr, 
							  RESOURCE_TYPE_CONTEXT );
	getCheckInternalResource2( iLocalContext, localContextInfoPtr, 
							   RESOURCE_TYPE_CONTEXT, cryptInfoPtr );
	if( !cryptInfoPtr->ctxPKC.keySet )
		{
		BIGNUM *tmp;

		/* Swap the newly-read parameters in the import context with the
		   uninitialised values in the import context */
		tmp = cryptInfoPtr->ctxPKC.dhParam_p;
		cryptInfoPtr->ctxPKC.dhParam_p = localContextInfoPtr->ctxPKC.dhParam_p;
		localContextInfoPtr->ctxPKC.dhParam_p = tmp;
		tmp = cryptInfoPtr->ctxPKC.dhParam_g;
		cryptInfoPtr->ctxPKC.dhParam_g = localContextInfoPtr->ctxPKC.dhParam_g;
		localContextInfoPtr->ctxPKC.dhParam_g = tmp;
		tmp = cryptInfoPtr->ctxPKC.dhParam_yPrime;
		cryptInfoPtr->ctxPKC.dhParam_yPrime = localContextInfoPtr->ctxPKC.dhParam_yPrime;
		localContextInfoPtr->ctxPKC.dhParam_yPrime = tmp;

		/* Perform an internal load */
		status = cryptInfoPtr->capabilityInfo->initKeyFunction( \
								cryptInfoPtr, NULL, LOAD_INTERNAL_PUBLIC );
		if( cryptStatusOK( status ) )
			cryptInfoPtr->ctxPKC.keySet = TRUE;
		}
	else
		/* Make sure the responders key was the same as the intiators key */
		if( memcmp( cryptInfoPtr->ctxPKC.keyID, localContextInfoPtr->ctxPKC.keyID,
					KEYID_SIZE ) )
			status = CRYPT_ERROR_WRONGKEY;
		else
			{
			BIGNUM *tmp;

			tmp = cryptInfoPtr->ctxPKC.dhParam_yPrime;
			cryptInfoPtr->ctxPKC.dhParam_yPrime = localContextInfoPtr->ctxPKC.dhParam_yPrime;
			localContextInfoPtr->ctxPKC.dhParam_yPrime = tmp;
			}
	unlockResource( localContextInfoPtr );
	unlockResource( cryptInfoPtr );
#endif /* 0 */
	krnlSendNotifier( iLocalContext, RESOURCE_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, RESOURCE_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, RESOURCE_IMESSAGE_SETATTRIBUTE, 
						 ( int * ) &iterations, CRYPT_CTXINFO_KEYING_ITERATIONS );
		setResourceData( &msgData, ( void * ) salt, 8 );
		krnlSendMessage( iSessionKeyContext, RESOURCE_IMESSAGE_SETATTRIBUTE_S, 
						 &msgData, CRYPT_CTXINFO_KEYING_SALT );
		setResourceData( &msgData, buffer, status );
		status = krnlSendMessage( iSessionKeyContext, 
								  RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
								  CRYPT_CTXINFO_KEYING_VALUE );
		}

	return( status );
	}

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

/* Get the issuerAndSerialNumber for a certificate */

static int getIssuerAndSerialNumber( CRYPT_HANDLE iCryptHandle,
									 BYTE **bufferPtr, int *lengthPtr )
	{
	RESOURCE_DATA msgData;
	BYTE *buffer = *bufferPtr;
	int status;

	/* Find out how large the data will be and allocate a buffer for it if
	   necessary */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusOK( status ) && msgData.length > 1024 && \
		( buffer = malloc( msgData.length ) ) == NULL )
		status = CRYPT_ERROR_MEMORY;
	if( cryptStatusError( status ) )
		return( status );

	/* Copy the data into the buffer */
	msgData.data = buffer;
	status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusError( status ) )
		{
		if( buffer != *bufferPtr )
			free( buffer );
		return( status );
		}
	*bufferPtr = msgData.data;
	*lengthPtr = msgData.length;

	return( CRYPT_OK );
	}

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

C_RET cryptImportKeyEx( C_IN void C_PTR encryptedKey,
						C_IN CRYPT_CONTEXT importKey,
						C_IN CRYPT_CONTEXT sessionKeyContext )
	{
	CRYPT_ALGO cryptAlgo;
	RESOURCE_MESSAGE_CHECK_TYPE checkType;
	int owner, originalOwner = CRYPT_UNUSED, encryptedKeyLength, status;

	/* Perform basic error checking */
	if( checkBadPtrRead( encryptedKey, MIN_CRYPT_OBJECTSIZE ) )
		return( CRYPT_ERROR_PARAM1 );

	/* Check the importing key */
	status = krnlSendMessage( importKey, RESOURCE_MESSAGE_GETATTRIBUTE, 
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM2 : status );
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		checkType = ( cryptAlgo == CRYPT_ALGO_DH ) ? \
					RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT : \
					RESOURCE_MESSAGE_CHECK_PKC_DECRYPT;
	else
		checkType = RESOURCE_MESSAGE_CHECK_CRYPT;
	status = krnlSendMessage( importKey, RESOURCE_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_PARAM2 : status );

	/* Check the session key */
	status = krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_CHECK, 
							  NULL, RESOURCE_MESSAGE_CHECK_CRYPT );
	if( status == CRYPT_OK )
		return( CRYPT_ERROR_INITED );	/* Shouldn't have key attr.present */
	if( cryptStatusError( status ) && status != CRYPT_ERROR_NOTINITED )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM3 : status );

	/* Try and determine the length of the encrypted key data.  This 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 */
	encryptedKeyLength = getObjectLength( encryptedKey, 512 );
	if( cryptStatusError( encryptedKeyLength ) )
		return( CRYPT_ERROR_PARAM1 );

	/* If the importing key is owned, bind the session key context to the same 
	   owner before we load a key into it.  We also need to save the original 
	   owner so we can undo the binding later if things fail */
	krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_GETATTRIBUTE,
					 &originalOwner, CRYPT_PROPERTY_OWNER );
	status = krnlSendMessage( importKey, RESOURCE_MESSAGE_GETATTRIBUTE,
							  &owner, CRYPT_PROPERTY_OWNER );
	if( cryptStatusOK( status ) && owner != CRYPT_UNUSED )
		krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_SETATTRIBUTE,
						 &owner, CRYPT_PROPERTY_OWNER );

	/* Import it as appropriate */
	if( cryptAlgo >= CRYPT_ALGO_FIRST_PKC && cryptAlgo <= CRYPT_ALGO_LAST_PKC )
		{
		if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_KEA )
			status = importKeyAgreeKey( encryptedKey, sessionKeyContext, 
										importKey );
		else
			status = importPublicKey( encryptedKey, encryptedKeyLength,
									  sessionKeyContext, importKey );
		}
	else
		status = importConventionalKey( encryptedKey, encryptedKeyLength,
										sessionKeyContext, importKey );

	/* If the import failed, return the session key context to its
	   original owner */
	if( cryptStatusError( status ) )
		krnlSendMessage( sessionKeyContext, RESOURCE_MESSAGE_SETATTRIBUTE,
						 &originalOwner, CRYPT_PROPERTY_OWNER );

	if( cryptArgError( status ) )
		/* If we get an argument error from the mechanism-level code, map the
		   mechanism 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,

⌨️ 快捷键说明

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