📄 dev_capi.c
字号:
/* Encrypt, decrypt. We always set the bFinal flag to FALSE since setting it
to TRUE tries to apply message padding, resets the IV, and various other
unwanted side-effects */
static int genericEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer,
const int length, const int outLength )
{
int resultLength = length;
if( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
&resultLength, outLength ) )
return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
return( CRYPT_OK );
}
static int genericDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer,
const int length, int *resultLength )
{
*resultLength = length;
if( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
resultLength ) )
return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
return( CRYPT_OK );
}
/* Clean up the object associated with a context */
static int genericEndFunction( CONTEXT_INFO *contextInfoPtr )
{
/* Destroy the object */
if( contextInfoPtr->capabilityInfo->keySize > 0 )
pCryptDestroyKey( contextInfoPtr->deviceObject );
else
pCryptDestroyHash( contextInfoPtr->deviceObject );
return( CRYPT_OK );
}
#if 0
/* 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 */
static int rsaSetPublicComponents( DEVICE_INFO *deviceInfo,
const CRYPT_CONTEXT iCryptContext,
const CK_OBJECT_HANDLE hRsaKey )
{
CK_ATTRIBUTE nTemplate = { CKA_MODULUS, NULL_PTR, CRYPT_MAX_PKCSIZE };
CK_ATTRIBUTE eTemplate = { CKA_PUBLIC_EXPONENT, NULL_PTR, CRYPT_MAX_PKCSIZE };
CK_RV status;
BYTE n[ CRYPT_MAX_PKCSIZE ], e[ CRYPT_MAX_PKCSIZE ];
BYTE keyDataBuffer[ CRYPT_MAX_PKCSIZE * 2 ];
RESOURCE_DATA msgData;
int keyDataSize, cryptStatus;
/* Get the public key components from the device. The odd two-phase
read is necessary for buggy implementations that fail if the given
size isn't exactly the same as the data size */
status = C_GetAttributeValue( cryptoapiInfo->hProv, hRsaKey,
&nTemplate, 1 );
if( status == CKR_OK )
{
nTemplate.pValue = n;
status = C_GetAttributeValue( cryptoapiInfo->hProv, hRsaKey,
&nTemplate, 1 );
}
cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
status = C_GetAttributeValue( cryptoapiInfo->hProv, hRsaKey,
&eTemplate, 1 );
if( status == CKR_OK )
{
eTemplate.pValue = e;
status = C_GetAttributeValue( cryptoapiInfo->hProv, hRsaKey,
&eTemplate, 1 );
}
cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
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 = keyDataSize = writeFlatPublicKey( NULL, 0, CRYPT_ALGO_RSA,
n, nTemplate.ulValueLen, e, eTemplate.ulValueLen,
NULL, 0, NULL, 0 );
if( !cryptStatusError( cryptStatus ) )
cryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,
CRYPT_ALGO_RSA, n, nTemplate.ulValueLen,
e, eTemplate.ulValueLen, NULL, 0, NULL, 0 );
if( cryptStatusOK( cryptStatus ) )
krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE,
( void * ) &nTemplate.ulValueLen,
CRYPT_IATTRIBUTE_KEYSIZE );
if( cryptStatusOK( cryptStatus ) )
{
setMessageData( &msgData, keyDataBuffer, keyDataSize );
cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData,
CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
}
return( cryptStatus );
}
static int rsaSetKeyInfo( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
const CK_OBJECT_HANDLE hPrivateKey,
const CK_OBJECT_HANDLE hPublicKey )
{
RESOURCE_DATA msgData;
BYTE idBuffer[ KEYID_SIZE ];
int cryptStatus;
/* 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 != CRYPT_UNUSED )
C_SetAttributeValue( cryptoapiInfo->hProv, hPublicKey,
&idTemplate, 1 );
C_SetAttributeValue( cryptoapiInfo->hProv, hPrivateKey,
&idTemplate, 1 );
}
return( cryptStatus );
}
#endif /* 0 */
static int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key,
const int keyLength )
{
#if 0
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 },
};
CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;
CRYPT_DEVICE iCryptDevice;
DEVICE_INFO *deviceInfo;
CK_OBJECT_HANDLE hRsaKey;
CK_RV status;
const int templateCount = rsaKey->isPublicKey ? 8 : 15;
int cryptStatus;
/* Get the info for the device associated with this context */
cryptStatus = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_GETDEPENDENT, &iCryptDevice,
OBJECT_TYPE_DEVICE );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = krnlGetObject( iCryptDevice, OBJECT_TYPE_DEVICE,
( void ** ) &deviceInfo,
CRYPT_ERROR_SIGNALLED );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
assert( !( deviceInfo->flags & DEVICE_READONLY ) );
/* Set up the key values */
rsaKeyTemplate[ 6 ].pValue = rsaKey->n;
rsaKeyTemplate[ 6 ].ulValueLen = bitsToBytes( rsaKey->nLen );
rsaKeyTemplate[ 7 ].pValue = rsaKey->e;
rsaKeyTemplate[ 7 ].ulValueLen = bitsToBytes( rsaKey->eLen );
if( !rsaKey->isPublicKey )
{
rsaKeyTemplate[ 9 ].pValue = rsaKey->d;
rsaKeyTemplate[ 9 ].ulValueLen = bitsToBytes( rsaKey->dLen );
rsaKeyTemplate[ 10 ].pValue = rsaKey->p;
rsaKeyTemplate[ 10 ].ulValueLen = bitsToBytes( rsaKey->pLen );
rsaKeyTemplate[ 11 ].pValue = rsaKey->q;
rsaKeyTemplate[ 11 ].ulValueLen = bitsToBytes( rsaKey->qLen );
rsaKeyTemplate[ 12 ].pValue = rsaKey->e1;
rsaKeyTemplate[ 12 ].ulValueLen = bitsToBytes( rsaKey->e1Len );
rsaKeyTemplate[ 13 ].pValue = rsaKey->e2;
rsaKeyTemplate[ 13 ].ulValueLen = bitsToBytes( rsaKey->e2Len );
rsaKeyTemplate[ 14 ].pValue = 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 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( cryptoapiInfo->hProv, rsaKeyTemplate,
templateCount, &hRsaKey );
zeroise( rsaKeyTemplate, sizeof( CK_ATTRIBUTE ) * templateCount );
cryptStatus = mapError( deviceInfo, 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( deviceInfo->objectHandle );
return( cryptStatus );
}
/* Send the keying info to the context and set up the key ID info */
cryptStatus = rsaSetPublicComponents( deviceInfo,
contextInfoPtr->objectHandle, hRsaKey );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = rsaSetKeyInfo( deviceInfo, contextInfoPtr,
hRsaKey, CRYPT_UNUSED );
if( cryptStatusError( cryptStatus ) )
C_DestroyObject( cryptoapiInfo->hProv, hRsaKey );
krnlReleaseObject( deviceInfo->objectHandle );
return( cryptStatus );
#endif /* 0 */
return( CRYPT_ERROR );
}
static int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )
{
#if 0
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, NULL, sizeof( CK_ULONG ) }
};
CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
CRYPT_DEVICE iCryptDevice;
DEVICE_INFO *deviceInfo;
CK_RV status;
int cryptStatus;
/* Get the info for the device associated with this context */
cryptStatus = krnlSendMessage( contextInfoPtr->objectHandle,
IMESSAGE_GETDEPENDENT, &iCryptDevice,
OBJECT_TYPE_DEVICE );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = krnlGetObject( iCryptDevice, OBJECT_TYPE_DEVICE,
( void ** ) &deviceInfo,
CRYPT_ERROR_SIGNALLED );
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
assert( !( deviceInfo->flags & DEVICE_READONLY ) );
/* Patch in the key size and generate the keys */
publicKeyTemplate[ 5 ].pValue = ( CK_VOID_PTR ) &modulusBits;
status = C_GenerateKeyPair( cryptoapiInfo->hProv,
( CK_MECHANISM_PTR ) &mechanism,
publicKeyTemplate, 6, privateKeyTemplate, 6,
&hPublicKey, &hPrivateKey );
cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
if( cryptStatusError( cryptStatus ) )
{
krnlReleaseObject( deviceInfo->objectHandle );
return( cryptStatus );
}
/* Send the keying info to the context and set up the key ID info */
cryptStatus = rsaSetPublicComponents( deviceInfo,
contextInfoPtr->objectHandle, hPublicKey );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = rsaSetKeyInfo( deviceInfo, contextInfoPtr, hPrivateKey,
hPublicKey );
if( cryptStatusError( cryptStatus ) )
{
C_DestroyObject( cryptoapiInfo->hProv, hPublicKey );
C_DestroyObject( cryptoapiInfo->hProv, hPrivateKey );
}
krnlReleaseObject( deviceInfo->objectHandle );
return( cryptStatus );
#endif /* 0 */
return( CRYPT_ERROR );
}
static int rsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
{
#if 0
static const CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };
CRYPT_DEVICE iCryptDevice;
DEVICE_INFO *deviceInfo;
BYTE *bufPtr = buffer;
const int keySize = bitsToBytes( contextInfoPtr->ctxPKC.keySizeBits );
int cryptStatus, i;
assert( length == keySize );
/* Undo the PKCS #1 padding to make CKM_RSA_PKCS look like
CKM_RSA_X_509
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -