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

📄 pkcs11_pkc.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
	MESSAGE_DATA msgData;
	BYTE idBuffer[ KEYID_SIZE + 8 ];
	int cryptStatus;

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

	/* Remember what we've set up */
	krnlSendMessage( contextInfoPtr->objectHandle, IMESSAGE_SETATTRIBUTE,
					 ( void * ) &hPrivateKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );

	/* Get the key ID from the context and use it as the object ID.  Since 
	   some objects won't allow after-the-event ID updates, we don't treat a
	   failure to update as an error */
	setMessageData( &msgData, idBuffer, KEYID_SIZE );
	cryptStatus = krnlSendMessage( contextInfoPtr->objectHandle, 
								   IMESSAGE_GETATTRIBUTE_S, &msgData, 
								   CRYPT_IATTRIBUTE_KEYID );
	if( cryptStatusOK( cryptStatus ) )
		{
		CK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };

		if( hPublicKey != CK_OBJECT_NONE )
			C_SetAttributeValue( pkcs11Info->hSession, hPublicKey, 
								 &idTemplate, 1 );
		C_SetAttributeValue( pkcs11Info->hSession, hPrivateKey, 
							 &idTemplate, 1 );
		}
	
	return( cryptStatus );
	}

static int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key, 
					   const int keyLength )
	{
	static const CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY;
	static const CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY;
	static const CK_KEY_TYPE type = CKK_RSA;
	static const CK_BBOOL bTrue = TRUE;
	CK_ATTRIBUTE rsaKeyTemplate[] = {
		/* Shared fields */
		{ CKA_CLASS, ( CK_VOID_PTR ) &privKeyClass, sizeof( CK_OBJECT_CLASS ) },
		{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &type, sizeof( CK_KEY_TYPE ) },
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
		{ CKA_MODULUS, NULL, 0 },
		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
		/* Private-key only fields */
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE_EXPONENT, NULL, 0 },
		{ CKA_PRIME_1, NULL, 0 },
		{ CKA_PRIME_2, NULL, 0 },
		{ CKA_EXPONENT_1, NULL, 0 },
		{ CKA_EXPONENT_2, NULL, 0 },
		{ CKA_COEFFICIENT, NULL, 0 },
		};
	const CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	CK_OBJECT_HANDLE hRsaKey;
	CK_RV status;
	const int templateCount = rsaKey->isPublicKey ? 8 : 15;
	int cryptStatus;

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

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

	/* Set up the key values */
	rsaKeyTemplate[ 6 ].pValue = ( CK_VOID_PTR ) rsaKey->n;
	rsaKeyTemplate[ 6 ].ulValueLen = bitsToBytes( rsaKey->nLen );
	rsaKeyTemplate[ 7 ].pValue = ( CK_VOID_PTR ) rsaKey->e;
	rsaKeyTemplate[ 7 ].ulValueLen = bitsToBytes( rsaKey->eLen );
	if( !rsaKey->isPublicKey )
		{
		rsaKeyTemplate[ 9 ].pValue = ( CK_VOID_PTR ) rsaKey->d;
		rsaKeyTemplate[ 9 ].ulValueLen = bitsToBytes( rsaKey->dLen );
		rsaKeyTemplate[ 10 ].pValue = ( CK_VOID_PTR ) rsaKey->p;
		rsaKeyTemplate[ 10 ].ulValueLen = bitsToBytes( rsaKey->pLen );
		rsaKeyTemplate[ 11 ].pValue = ( CK_VOID_PTR ) rsaKey->q;
		rsaKeyTemplate[ 11 ].ulValueLen = bitsToBytes( rsaKey->qLen );
		rsaKeyTemplate[ 12 ].pValue = ( CK_VOID_PTR ) rsaKey->e1;
		rsaKeyTemplate[ 12 ].ulValueLen = bitsToBytes( rsaKey->e1Len );
		rsaKeyTemplate[ 13 ].pValue = ( CK_VOID_PTR ) rsaKey->e2;
		rsaKeyTemplate[ 13 ].ulValueLen = bitsToBytes( rsaKey->e2Len );
		rsaKeyTemplate[ 14 ].pValue = ( CK_VOID_PTR ) rsaKey->u;
		rsaKeyTemplate[ 14 ].ulValueLen = bitsToBytes( rsaKey->uLen );
		}
	else
		{
		/* If it's a public key, we need to change the type and indication of 
		   the operations that it's allowed to perform */
		rsaKeyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &pubKeyClass;
		rsaKeyTemplate[ 3 ].type = CKA_VERIFY;
		rsaKeyTemplate[ 4 ].type = CKA_ENCRYPT;
		}

	/* Load the key into the token */
	status = C_CreateObject( pkcs11Info->hSession, rsaKeyTemplate, 
							 templateCount, &hRsaKey );
	zeroise( rsaKeyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
	cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
	if( cryptStatusError( cryptStatus ) )
		{
		/* If we're trying to set a public key and this is one of those
		   tinkertoy tokens that only does private-key ops, return a more
		   appropriate error code */
		if( rsaKey->isPublicKey && \
			contextInfoPtr->capabilityInfo->encryptFunction == NULL &&
			contextInfoPtr->capabilityInfo->sigCheckFunction == NULL )
			cryptStatus = CRYPT_ERROR_NOTAVAIL;

		krnlReleaseObject( iCryptDevice );
		return( cryptStatus );
		}

	/* Send the keying info to the context and set up the key ID info */
	cryptStatus = rsaSetPublicComponents( pkcs11Info, 
										  contextInfoPtr->objectHandle, hRsaKey,
										  FALSE );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = rsaSetKeyInfo( pkcs11Info, contextInfoPtr, 
									 hRsaKey, CK_OBJECT_NONE );
	if( cryptStatusError( cryptStatus ) )
		C_DestroyObject( pkcs11Info->hSession, hRsaKey );
	else
		/* Remember that this object is backed by a crypto device */
		contextInfoPtr->flags |= CONTEXT_FLAG_PERSISTENT;

	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )
	{
	static const CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
	static const CK_BBOOL bTrue = TRUE;
	static const BYTE exponent[] = { 0x01, 0x00, 0x01 };
	const CK_ULONG modulusBits = keysizeBits;
	CK_ATTRIBUTE privateKeyTemplate[] = {
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
		{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		};
	CK_ATTRIBUTE publicKeyTemplate[] = {
		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
		{ CKA_ENCRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
		{ CKA_PUBLIC_EXPONENT, ( CK_VOID_PTR ) exponent, sizeof( exponent ) },
		{ CKA_MODULUS_BITS, ( CK_VOID_PTR ) &modulusBits, sizeof( CK_ULONG ) }
		};
	CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	CK_RV status;
	int cryptStatus;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( keysizeBits >= bytesToBits( MIN_PKCSIZE ) && \
			keysizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );

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

	/* Patch in the key size and generate the keys */
	status = C_GenerateKeyPair( pkcs11Info->hSession,
								( CK_MECHANISM_PTR ) &mechanism,
								publicKeyTemplate, 6, privateKeyTemplate, 6,
								&hPublicKey, &hPrivateKey );
	cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
	if( cryptStatusError( cryptStatus ) )
		{
		krnlReleaseObject( iCryptDevice );
		return( cryptStatus );
		}

	/* Send the keying info to the context and set up the key ID info */
	cryptStatus = rsaSetPublicComponents( pkcs11Info, 
										  contextInfoPtr->objectHandle, 
										  hPublicKey, FALSE );
	if( cryptStatusOK( cryptStatus ) )
		cryptStatus = rsaSetKeyInfo( pkcs11Info, contextInfoPtr, hPrivateKey, 
									 hPublicKey );
	if( cryptStatusError( cryptStatus ) )
		{
		C_DestroyObject( pkcs11Info->hSession, hPublicKey );
		C_DestroyObject( pkcs11Info->hSession, hPrivateKey );
		}
	else
		/* Remember that this object is backed by a crypto device */
		contextInfoPtr->flags |= CONTEXT_FLAG_PERSISTENT;

	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int rsaSign( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
	{
	static const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	BYTE *bufPtr = buffer;
	const int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
	int cryptStatus, i;

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( buffer, length ) );
	assert( length == keySize );

	/* Undo the PKCS #1 padding to make CKM_RSA_PKCS look like 
	   CKM_RSA_X_509 */
	assert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 1 && bufPtr[ 2 ] == 0xFF );
	for( i = 2; i < keySize; i++ )
		if( bufPtr[ i ] == 0 )
			break;
	i++;	/* Skip final 0 byte */

	/* Get the info for the device associated with this context */
	cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle, 
										&iCryptDevice, &pkcs11Info );
	if( cryptStatusError( cryptStatus ) )
		return( cryptStatus );
	cryptStatus = genericSign( pkcs11Info, contextInfoPtr, &mechanism, 
							   bufPtr + i, keySize - i, buffer, keySize );
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int rsaVerify( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
	{
	static const CK_MECHANISM mechanism = { CKM_RSA_X_509, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	BYTE data[ CRYPT_MAX_PKCSIZE + 8 ];
	const int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
	int cryptStatus;

	/* This function is present but isn't used as part of any normal 
	   operation because cryptlib does the same thing much faster in 
	   software and because some tokens don't support public-key 
	   operations */

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( buffer, length ) );
	assert( length == keySize );

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

static int rsaEncrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
	{
	static const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	BYTE *bufPtr = buffer;
	const int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
	int cryptStatus, i;

	/* This function is present but isn't used as part of any normal 
	   operation because cryptlib does the same thing much faster in 
	   software and because some tokens don't support public-key 
	   operations.  The only way that it can be invoked is by calling
	   cryptEncrypt() directly on a device context */

	assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
	assert( isWritePtr( buffer, length ) );
	assert( length == keySize );

	/* Undo the PKCS #1 padding to make CKM_RSA_PKCS look like 
	   CKM_RSA_X_509 */
	assert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 2 );
	for( i = 2; i < keySize; i++ )
		if( bufPtr[ i ] == 0 )
			break;
	i++;	/* Skip final 0 byte */
	memmove( bufPtr, bufPtr + i, keySize - i );

	/* 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, 
								  bufPtr, keySize - i, keySize );
	krnlReleaseObject( iCryptDevice );
	return( cryptStatus );
	}

static int rsaDecrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
	{
	static const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };
	CRYPT_DEVICE iCryptDevice;
	PKCS11_INFO *pkcs11Info;
	MESSAGE_DATA msgData;
	BYTE *bufPtr = buffer;
	const int keySize = bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits );
	int cryptStatus, i, resultLen;

⌨️ 快捷键说明

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