📄 pkcs11_pkc.c
字号:
{
setMessageData( &msgData, keyDataBuffer, keyDataSize );
cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData,
CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &pLen, CRYPT_IATTRIBUTE_KEYSIZE );
}
return( cryptStatus );
}
static int dhInitKey( CONTEXT_INFO *contextInfoPtr, const void *key,
const int keyLength )
{
static const CK_MECHANISM mechanism = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
static const CK_BBOOL bTrue = TRUE;
CK_ATTRIBUTE privateKeyTemplate[] = {
{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
{ CKA_DERIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
};
CK_ATTRIBUTE publicKeyTemplate[] = {
{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
{ CKA_DERIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
{ CKA_PRIME, NULL, 0 },
{ CKA_BASE, NULL, 0 },
};
CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
CK_RV status;
const CRYPT_PKCINFO_DLP *dhKey = ( CRYPT_PKCINFO_DLP * ) key;
CRYPT_DEVICE iCryptDevice;
PKCS11_INFO *pkcs11Info;
int cryptStatus;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isReadPtr( key, keyLength ) );
assert( keyLength == sizeof( CRYPT_PKCINFO_DLP ) );
/* Get the info for the device associated with this context */
cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
&iCryptDevice, &pkcs11Info );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Generate the keys. We can't set CKA_SENSITIVE for the private key
because although this is appropriate for the key (we don't want people
extracting the x value), some implementations carry it over to the
derived key in phase 2 and make that non-extractable as well */
publicKeyTemplate[ 2 ].pValue = ( CK_VOID_PTR ) dhKey->p;
publicKeyTemplate[ 2 ].ulValueLen = bitsToBytes( dhKey->pLen );
publicKeyTemplate[ 3 ].pValue = ( CK_VOID_PTR ) dhKey->g;
publicKeyTemplate[ 3 ].ulValueLen = bitsToBytes( dhKey->gLen );
status = C_GenerateKeyPair( pkcs11Info->hSession,
( CK_MECHANISM_PTR ) &mechanism,
( CK_ATTRIBUTE_PTR ) publicKeyTemplate, 4,
( CK_ATTRIBUTE_PTR ) privateKeyTemplate, 3,
&hPublicKey, &hPrivateKey );
cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
if( cryptStatusError( cryptStatus ) )
{
krnlReleaseObject( iCryptDevice );
return( cryptStatus );
}
/* Send the keying info to the context */
cryptStatus = dhSetPublicComponents( pkcs11Info,
contextInfoPtr->objectHandle,
hPublicKey, dhKey->q,
bitsToBytes( dhKey->qLen ) );
if( cryptStatusError( cryptStatus ) )
{
krnlReleaseObject( iCryptDevice );
return( cryptStatus );
}
/* Remember what we've set up */
krnlSendMessage( contextInfoPtr->objectHandle, IMESSAGE_SETATTRIBUTE,
( void * ) &hPrivateKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );
contextInfoPtr->altDeviceObject = hPublicKey;
krnlReleaseObject( iCryptDevice );
return( cryptStatus );
}
static int dhGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )
{
CRYPT_PKCINFO_DLP dhKey;
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
BYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 3 ) + 8 ], label[ 8 + 8 ];
STREAM stream;
long length;
int cryptStatus;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( keysizeBits >= bytesToBits( MIN_PKCSIZE ) && \
keysizeBits <= bytesToBits( CRYPT_MAX_PKCSIZE ) );
/* CKM_DH_KEY_PAIR_GEN is really a Clayton's key generation mechanism
since it doesn't actually generate the p, g values. Because of this
we have to generate half the key ourselves in a native context, then
copy portions from the native context over in flat form and complete
the keygen via the device. The easiest way to do this is to create a
native DH context, generate a key, grab the public portions, and
destroy the context again. Since the keygen can take awhile and
doesn't require the device, we do it before we grab the device */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DH );
cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_CREATEOBJECT, &createInfo,
OBJECT_TYPE_CONTEXT );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
setMessageData( &msgData, label, 8 );
krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
cryptStatus = krnlSendNotifier( createInfo.cryptHandle,
IMESSAGE_CTX_GENKEY );
if( cryptStatusOK( cryptStatus ) )
{
setMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 3 );
cryptStatus = krnlSendMessage( createInfo.cryptHandle,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_KEY_SPKI );
}
krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Set up the public key info by extracting the flat values from the
SubjectPublicKeyInfo. Note that the data used is represented in
DER-canonical form, there may be PKCS #11 implementations that can't
handle this (for example they may require p to be zero-padded to make
it exactly n bytes rather than (say) n - 1 bytes if the high byte is
zero) */
cryptInitComponents( &dhKey, CRYPT_KEYTYPE_PUBLIC );
sMemConnect( &stream, pubkeyBuffer, msgData.length );
readSequence( &stream, NULL ); /* SEQUENCE */
readSequence( &stream, NULL ); /* SEQUENCE */
readUniversal( &stream ); /* OID */
readSequence( &stream, NULL ); /* SEQUENCE */
readGenericHole( &stream, &length, 16, BER_INTEGER ); /* p */
sread( &stream, dhKey.p, length );
dhKey.pLen = bytesToBits( length );
readGenericHole( &stream, &length, 16, BER_INTEGER ); /* q */
sread( &stream, dhKey.q, length );
dhKey.qLen = bytesToBits( length );
readGenericHole( &stream, &length, 16, BER_INTEGER ); /* g */
sread( &stream, dhKey.g, length );
dhKey.gLen = bytesToBits( length );
assert( sStatusOK( &stream ) );
sMemDisconnect( &stream );
/* From here on it's a standard DH key load */
return( dhInitKey( contextInfoPtr, &dhKey, sizeof( CRYPT_PKCINFO_DLP ) ) );
}
static int dhEncrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
{
CK_ATTRIBUTE yValueTemplate = { CKA_VALUE, NULL, CRYPT_MAX_PKCSIZE };
CK_RV status;
CRYPT_DEVICE iCryptDevice;
PKCS11_INFO *pkcs11Info;
KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
int cryptStatus;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isWritePtr( buffer, length ) );
assert( length == sizeof( KEYAGREE_PARAMS ) );
/* Get the info for the device associated with this context */
cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
&iCryptDevice, &pkcs11Info );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Get the y value from phase 1 of the DH key agreement (generated when
the key was loaded/generated) from the device. The odd two-phase y
value read is necessary for buggy implementations that fail if the
given size isn't exactly the same as the data size */
status = C_GetAttributeValue( pkcs11Info->hSession,
contextInfoPtr->altDeviceObject,
&yValueTemplate, 1 );
if( status == CKR_OK )
{
yValueTemplate.pValue = keyAgreeParams->publicValue;
status = C_GetAttributeValue( pkcs11Info->hSession,
contextInfoPtr->altDeviceObject,
&yValueTemplate, 1 );
}
if( status == CKR_OK )
keyAgreeParams->publicValueLen = yValueTemplate.ulValueLen;
cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
krnlReleaseObject( iCryptDevice );
return( cryptStatus );
}
static int dhDecrypt( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int length )
{
static const CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY;
static const CK_KEY_TYPE secretKeyType = CKK_GENERIC_SECRET;
static const CK_BBOOL bTrue = TRUE;
CK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, NULL_PTR, 0 };
CK_ULONG valueLen;
CK_ATTRIBUTE symTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &secretKeyClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_KEY_TYPE, ( CK_VOID_PTR ) &secretKeyType, sizeof( CK_KEY_TYPE ) },
{ CKA_EXTRACTABLE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
{ CKA_VALUE_LEN, &valueLen, sizeof( CK_ULONG ) }
};
CK_OBJECT_HANDLE hSymKey;
CK_RV status;
CRYPT_DEVICE iCryptDevice;
PKCS11_INFO *pkcs11Info;
KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
int cryptStatus;
assert( isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
assert( isWritePtr( buffer, length ) );
assert( length == sizeof( KEYAGREE_PARAMS ) );
assert( keyAgreeParams->publicValue != NULL && \
keyAgreeParams->publicValueLen >= MIN_PKCSIZE );
/* Get the info for the device associated with this context */
cryptStatus = getContextDeviceInfo( contextInfoPtr->objectHandle,
&iCryptDevice, &pkcs11Info );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Use the supplied y value to perform phase 2 of the DH key agreement.
Since PKCS #11 mechanisms don't allow the resulting data to be
returned directly, we move it into a generic secret-key object and
then read it from that */
valueLen = keyAgreeParams->publicValueLen; /* symTemplate[4].pValue */
mechanism.pParameter = keyAgreeParams->publicValue;
mechanism.ulParameterLen = keyAgreeParams->publicValueLen;
status = C_DeriveKey( pkcs11Info->hSession, &mechanism,
contextInfoPtr->deviceObject,
symTemplate, 4, &hSymKey );
if( status == CKR_OK )
{
CK_ATTRIBUTE valueTemplate[] = { CKA_VALUE, keyAgreeParams->wrappedKey,
valueLen };
status = C_GetAttributeValue( pkcs11Info->hSession,
hSymKey, valueTemplate, 1 );
if( status == CKR_OK )
keyAgreeParams->wrappedKeyLen = valueTemplate[ 0 ].ulValueLen;
C_DestroyObject( pkcs11Info->hSession, hSymKey );
}
cryptStatus = pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED );
krnlReleaseObject( iCryptDevice );
return( cryptStatus );
}
/****************************************************************************
* *
* RSA Mapping Functions *
* *
****************************************************************************/
/* RSA algorithm-specific mapping functions. Externally we always appear to
use the X.509 (raw) mechanism for the encrypt/decrypt/sign/verify
functions since cryptlib does its own padding (with workarounds for
various bugs and peculiarities). Internally however we have to use the
PKCS mechanism since some implementations don't support the X.509
mechanism, and add/remove the padding to fake out the presence of a raw
RSA mechanism */
int rsaSetPublicComponents( PKCS11_INFO *pkcs11Info,
const CRYPT_CONTEXT iCryptContext,
const CK_OBJECT_HANDLE hRsaKey,
const BOOLEAN nativeContext )
{
BYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];
BYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];
MESSAGE_DATA msgData;
int nLen, eLen = DUMMY_INIT, keyDataSize, cryptStatus;
assert( isWritePtr( pkcs11Info, sizeof( PKCS11_INFO ) ) );
assert( isHandleRangeValid( iCryptContext ) );
/* Get the public key components from the device */
cryptStatus = readAttributeValue( pkcs11Info, hRsaKey, CKA_MODULUS,
n, CRYPT_MAX_PKCSIZE, &nLen );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = readAttributeValue( pkcs11Info, hRsaKey, CKA_PUBLIC_EXPONENT,
e, CRYPT_MAX_PKCSIZE, &eLen );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
/* Send the public key data to the context. We send the keying info as
CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than CRYPT_IATTRIBUTE_KEY_SPKI
since the latter transitions the context into the high state. We
don't want to do this because we're already in the middle of processing
a message that does this on completion, all we're doing here is
sending in encoded public key data for use by objects such as
certificates */
cryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,
&keyDataSize, CRYPT_ALGO_RSA,
n, nLen, e, eLen, NULL, 0, NULL, 0 );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
setMessageData( &msgData, keyDataBuffer, keyDataSize );
if( nativeContext )
return( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI ) );
cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &nLen,
CRYPT_IATTRIBUTE_KEYSIZE );
return( cryptStatus );
}
static int rsaSetKeyInfo( PKCS11_INFO *pkcs11Info,
CONTEXT_INFO *contextInfoPtr,
const CK_OBJECT_HANDLE hPrivateKey,
const CK_OBJECT_HANDLE hPublicKey )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -