📄 pkcs11_pkc.c
字号:
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 + -