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

📄 pkcs11.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isReadPtr( key, keyLength ) );

	/* If this is meant to be a persistent object, modify the template to 
	   make it a persistent token object and adjust the template entry count
	   to include the object label */
	if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
		keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;

	return( initKey( contextInfoPtr, keyTemplate, templateCount, 
					 key, keyLength ) );
	}

static int hmacInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, 
						const int keyLength )
	{
	static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
	static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
	const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
	CK_ATTRIBUTE keyTemplate[] = {
		/* General-purpose fields */
		{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VALUE, NULL_PTR, 0 },
		/* Persistent-object only fields */
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
		};
	const int templateCount = \
				( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isReadPtr( key, keyLength ) );

	/* If this is meant to be a persistent object, modify the template to 
	   make it a persistent token object and adjust the template entry count
	   to include the object label */
	if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
		keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;

	return( initKey( contextInfoPtr, keyTemplate, templateCount, 
					 key, keyLength ) );
	}

/* Generate a key into a device object.  Normally we generate keys inside
   cryptlib and load them into the device object (so a keygen becomes a
   keygen inside cryptlib followed by a cipherInitKey()) in order to make 
   sure that the key data is accessible from the context.  If we didn't do 
   this, the user would have to be very careful to perform all key wrap/
   unwrap operations only via device objects.  This is particularly
   problematic with public-key operations since cryptlib always instantiates
   public-key objects as cryptlib native objects since they're so much 
   quicker in that form.  So for example importing a certificate and then
   using it to wrap a conventional encryption key that's been generated in
   a device is impossible because the key to wrap isn't accessible to the
   public-key context tied to the certificate.  Because of this, 
   USE_HW_KEYGEN should be used with great care */

#ifdef USE_HW_KEYGEN

static int generateKey( CONTEXT_INFO *contextInfoPtr, 
						CK_ATTRIBUTE *keyTemplate, const int templateCount,
						const BOOLEAN isMAC )
	{
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	CK_MECHANISM mechanism = { contextInfoPtr->capabilityInfo->paramKeyGen, 
							   NULL_PTR, 0 };
	CK_OBJECT_HANDLE hObject;
	CK_RV status;
	int cryptStatus;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( keyTemplate, \
						templateCount * sizeof( CK_ATTRIBUTE ) ) );

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	/* Generate the key into the token */
	status = C_GenerateKey( pkcs11Info->hSession, &mechanism, 
							keyTemplate, templateCount, &hObject );
	cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
	if( cryptStatusOK( cryptStatus ) )
		{
		assert( hObject != CK_OBJECT_NONE );

		contextInfoPtr->deviceObject = hObject;
		}
	zeroise( keyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int cipherGenerateKey( CONTEXT_INFO *contextInfoPtr, 
							  const int keySizeBits )
	{
	static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
	static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
	const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
	const CK_ULONG length = bitsToBytes( keySizeBits );
	CK_ATTRIBUTE keyTemplate[] = {
		/* General-purpose fields */
		{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },
		/* Persistent-object only fields */
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
		};
	const int templateCount = \
				( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	/* If this is meant to be a persistent object, modify the template to 
	   make it a persistent token object and adjust the template entry count
	   to include the object label */
	if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
		keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;

	return( generateKey( contextInfoPtr, keyTemplate, templateCount, FALSE ) );
	}

static int hmacGenerateKey( CONTEXT_INFO *contextInfoPtr, 
							const int keySizeBits )
	{
	static const CK_OBJECT_CLASS class = CKO_SECRET_KEY;
	static const CK_BBOOL bFalse = FALSE, bTrue = TRUE;
	const CK_KEY_TYPE type = contextInfoPtr->capabilityInfo->paramKeyType;
	const CK_ULONG length = bitsToBytes( keySizeBits );
	CK_ATTRIBUTE keyTemplate[] = {
		/* General-purpose fields */
		{ CKA_CLASS, ( CK_VOID_PTR ) &class, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bFalse, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VALUE_LEN, ( CK_VOID_PTR ) &length, sizeof( CK_ULONG ) },
		/* Persistent-object only fields */
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize }
		};
	const int templateCount = \
				( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT ) ? 9 : 8;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );

	/* If this is meant to be a persistent object, modify the template to 
	   make it a persistent token object and adjust the template entry count
	   to include the object label */
	if( contextInfoPtr->flags & CONTEXT_FLAG_PERSISTENT )
		keyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) &bTrue;

	return( generateKey( contextInfoPtr, keyTemplate, templateCount, TRUE ) );
	}

#else

#define cipherGenerateKey	NULL
#define hmacGenerateKey		NULL

#endif /* USE_HW_KEYGEN */

/****************************************************************************
*																			*
*						 Conventional Crypto Mapping Functions				*
*																			*
****************************************************************************/

/* Set up algorithm-specific encryption parameters */

static int initCryptParams( CONTEXT_INFO *contextInfoPtr, void *paramData )
	{
	const int ivSize = contextInfoPtr->capabilityInfo->blockSize;

	if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC2 )
		{
		if( contextInfoPtr->ctxConv->mode == CRYPT_MODE_ECB )
			{
			CK_RC2_PARAMS_PTR rc2params = ( CK_RC2_PARAMS_PTR ) paramData;

			*rc2params = 128;
			return( sizeof( CK_RC2_PARAMS ) );
			}
		else
			{
			CK_RC2_CBC_PARAMS_PTR rc2params = ( CK_RC2_CBC_PARAMS_PTR ) paramData;

			rc2params->ulEffectiveBits = 128;
			memcpy( rc2params->iv, contextInfoPtr->ctxConv->currentIV, ivSize );
			return( sizeof( CK_RC2_CBC_PARAMS ) );
			}
		}
	if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RC5 )
		{
		if( contextInfoPtr->ctxConv->mode == CRYPT_MODE_ECB )
			{
			CK_RC5_PARAMS_PTR rc5params = ( CK_RC5_PARAMS_PTR ) paramData;

			rc5params->ulWordsize = 4;	/* Word size in bytes = blocksize/2 */
			rc5params->ulRounds = 12;
			return( sizeof( CK_RC5_PARAMS ) );
			}
		else
			{
			CK_RC5_CBC_PARAMS_PTR rc5params = ( CK_RC5_CBC_PARAMS_PTR ) paramData;

			rc5params->ulWordsize = 4;	/* Word size in bytes = blocksize/2 */
			rc5params->ulRounds = 12;
			rc5params->pIv = contextInfoPtr->ctxConv->currentIV;
			rc5params->ulIvLen = ivSize;
			return( sizeof( CK_RC5_CBC_PARAMS ) );
			}
		}
	return( 0 );
	}

/* Encrypt/decrypt data */

static int cipherEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, 
						  int length, const CK_MECHANISM_TYPE mechanismType )
	{
	CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	BYTE paramDataBuffer[ 64 + 8 ];
	const int ivSize = contextInfoPtr->capabilityInfo->blockSize;
	int paramSize, cryptStatus;

	/* Set up algorithm and mode-specific parameters */
	paramSize = initCryptParams( contextInfoPtr, &paramDataBuffer );
	if( paramSize > 0 )
		{
		mechanism.pParameter = paramDataBuffer;
		mechanism.ulParameterLen = paramSize;
		}
	else
		{
		/* Even if there are no algorithm-specific parameters, there may 
		   still be a mode-specific IV parameter */
		if( needsIV( contextInfoPtr->ctxConv->mode ) && \
			!isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
			{
			mechanism.pParameter = contextInfoPtr->ctxConv->currentIV;
			mechanism.ulParameterLen = ivSize;
			}
		}

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	cryptStatus = genericEncrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,
								  length, length );
	if( cryptStatusOK( cryptStatus ) )
		{
		if( needsIV( contextInfoPtr->ctxConv->mode ) && \
			!isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
			{
			/* Since PKCS #11 assumes that either all data is encrypted at 
			   once or that a given mechanism is devoted entirely to a single 
			   operation, we have to preserve the state (the IV) across 
			   calls */
			memcpy( contextInfoPtr->ctxConv->currentIV, \
					( BYTE * ) buffer + length - ivSize, ivSize );
			}
		}
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int cipherDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, 
						  int length, const CK_MECHANISM_TYPE mechanismType )
	{
	CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	BYTE paramDataBuffer[ 64 + 8 ], ivBuffer[ CRYPT_MAX_IVSIZE + 8 ];
	const int ivSize = contextInfoPtr->capabilityInfo->blockSize;
	int paramSize, cryptStatus;

	/* Set up algorithm and mode-specific parameters */
	paramSize = initCryptParams( contextInfoPtr, &paramDataBuffer );
	if( paramSize > 0 )
		{
		mechanism.pParameter = paramDataBuffer;
		mechanism.ulParameterLen = paramSize;
		}
	else
		/* Even if there are no algorithm-specific parameters, there may 
		   still be a mode-specific IV parameter.  In addition we have to
		   save the end of the ciphertext as the IV for the next block if
		   this is required */
		if( needsIV( contextInfoPtr->ctxConv->mode ) && \
			!isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
			{
			mechanism.pParameter = contextInfoPtr->ctxConv->currentIV;
			mechanism.ulParameterLen = ivSize;
			}
	if( needsIV( contextInfoPtr->ctxConv->mode ) && \
		!isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
		memcpy( ivBuffer, ( BYTE * ) buffer + length - ivSize, ivSize );

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );

	cryptStatus = genericDecrypt( pkcs11Info, contextInfoPtr, &mechanism, buffer,
								  length );
	if( cryptStatusOK( cryptStatus ) )
		{
		if( needsIV( contextInfoPtr->ctxConv->mode ) && \
			!isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
			{
			/* Since PKCS #11 assumes that either all data is encrypted at 
			   once or that a given mechanism is devoted entirely to a single 
			   operation, we have to preserve the state (the IV) across 
			   calls */
			memcpy( contextInfoPtr->ctxConv->currentIV, ivBuffer, ivSize );
			}
		}
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

/* Map a cryptlib algorithm and mode to a PKCS #11 mechanism type, with
   shortcuts for the most frequently-used algorithm(s) */

static int cipherEncryptECB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, 
							 int length )
	{
	if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_3DES )
		return( cipherEncrypt( contextInfoPtr, buffer, length, CKM_DES3_ECB ) );
	if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_AES )
		return( cipherEncrypt( contextInfoPtr, buffer, length, CKM_AES_ECB ) );
	return( cipherEncrypt( contextInfoPtr, buffer, length, 
				getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo, 
							  CRYPT_MODE_ECB ) ) );
	}
static int cipherEncryptCBC( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, 
							 int length )
	{
	return( cipherEncrypt( contextInfoPtr, buffer, length, 
						   contextInfoPtr->capabilityInfo->paramDefaultMech ) );
	}
#ifdef USE_SKIPJACK
static int cipherEncryptCFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, 
							 int length )
	{
	return( cipherEncrypt( contextInfoPtr, buffer, length, 
				getMechanism( MECH_CONV, contextInfoPtr->capabilityInfo->cryptAlgo, 
							  CRYPT_MODE_CFB ) ) );

⌨️ 快捷键说明

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