📄 dev_capi.c
字号:
if( cryptStatusError( cryptStatus ) )
return( cryptStatus );
certPresent = TRUE;
}
else
{
cryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert,
( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
FINDCERT_NORMAL : FINDCERT_DATAONLY );
if( cryptStatusError( cryptStatus ) )
{
/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
there's no cert present, however anything else is an error. In
addition if we've got a private key whose only function is to
point to an associated cert then not finding anything is also
an error */
if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
return( cryptStatus );
}
else
{
/* We got the cert, if we're being asked for a public key then
we've created a native object to contain it so we return that */
certPresent = TRUE;
if( itemType == KEYMGMT_ITEM_PUBLICKEY )
{
*iCryptContext = iCryptCert;
return( CRYPT_OK );
}
}
}
/* Get the permitted capabilities for the object */
if( readFlag( deviceInfo, hObject, CKA_ENCRYPT ) || \
readFlag( deviceInfo, hObject, CKA_UNWRAP ) )
{
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_ALL );
cryptAllowed = TRUE;
}
if( readFlag( deviceInfo, hObject, CKA_DECRYPT ) || \
readFlag( deviceInfo, hObject, CKA_UNWRAP ) )
{
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_ALL );
cryptAllowed = TRUE;
}
if( readFlag( deviceInfo, hObject, CKA_SIGN ) )
{
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_ALL );
sigAllowed = TRUE;
}
if( readFlag( deviceInfo, hObject, CKA_VERIFY ) )
{
actionFlags |= MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_ALL );
sigAllowed = TRUE;
}
if( cryptAlgo == CRYPT_ALGO_RSA )
{
/* If there are any restrictions on the key usage, we have to make it
internal-only because of RSA's signature/encryption duality */
if( !( cryptAllowed && sigAllowed ) )
actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
}
else
/* Because of the special-case data formatting requirements for DLP
algorithms, we make the usage internal-only */
actionFlags = MK_ACTION_PERM_NONE_EXTERNAL( actionFlags );
if( !actionFlags )
{
/* If no usage is allowed, we can't do anything with the object so
we don't even try to create it */
if( certPresent )
krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
return( CRYPT_ERROR_PERMISSION );
}
/* Create a dummy context for the key, remember the device it's
contained in, the handle for the device-internal key, and the object's
label, mark it as initialised (i.e. with a key loaded), and if there's a
cert present attach it to the context. The cert is an internal object
used only by the context so we tell the kernel to mark it as owned by
the context only */
cryptStatus = getObjectLabel( deviceInfo, hObject, label, &labelLength );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = createContextFromCapability( iCryptContext,
deviceInfo->ownerHandle, capabilityInfoPtr,
CREATEOBJECT_FLAG_DUMMY );
if( cryptStatusError( cryptStatus ) )
{
if( certPresent )
krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
return( cryptStatus );
}
krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
&deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &hObject,
CRYPT_IATTRIBUTE_DEVICEOBJECT );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE, &actionFlags,
CRYPT_IATTRIBUTE_ACTIONPERMS );
if( labelLength <= 0 )
{
/* If there's no label present, use a dummy value */
strcpy( label, "Label-less PKCS #11 key" );
labelLength = strlen( label );
}
setMessageData( &msgData, label, labelLength );
krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_LABEL );
if( keyType == CKK_RSA )
/* Send the keying info to the context. This is only possible for
RSA keys since it's not possible to read y from a DSA private
key object (see the comments in the DSA code for more on this),
however the only time this is necessary is when a cert is being
generated for a key that was pre-generated in the device by
someone else, which is typically done in Europe where DSA isn't
used so this shouldn't be a problem */
cryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext,
hObject );
else
cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
&keySize, CRYPT_IATTRIBUTE_KEYSIZE );
if( cryptStatusOK( cryptStatus ) )
cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_UNUSED,
CRYPT_IATTRIBUTE_INITIALISED );
if( certPresent && cryptStatusOK( cryptStatus ) )
cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
&iCryptCert, SETDEP_OPTION_NOINCREF );
if( cryptStatusError( cryptStatus ) && certPresent )
krnlSendNotifier( iCryptCert, IMESSAGE_DECREFCOUNT );
return( cryptStatus );
#endif
return( CRYPT_ERROR );
}
/* Update a device with a certificate */
static int setItemFunction( DEVICE_INFO *deviceInfo,
const CRYPT_HANDLE iCryptHandle )
{
CRYPT_CERTIFICATE iCryptCert;
int status;
/* Lock the cert for our exclusive use (in case it's a cert chain, we
also select the first cert in the chain), update the device with the
cert, and unlock it to allow others access */
krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert,
OBJECT_TYPE_CERTIFICATE );
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
#if 0
status = updateCertificate( deviceInfo, iCryptCert );
#endif
krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE,
CRYPT_IATTRIBUTE_LOCKED );
return( status );
}
/* Delete an object in a device */
static int deleteItemFunction( DEVICE_INFO *deviceInfo,
const KEYMGMT_ITEM_TYPE itemType,
const CRYPT_KEYID_TYPE keyIDtype,
const void *keyID, const int keyIDlength )
{
#if 0
static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
CK_ATTRIBUTE certTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
};
CK_ATTRIBUTE keyTemplate[] = {
{ CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },
{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
};
CK_OBJECT_HANDLE hPrivkey = CRYPT_ERROR, hCertificate = CRYPT_ERROR;
CK_OBJECT_HANDLE hPubkey = CRYPT_ERROR;
CK_RV status;
int cryptStatus;
assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
itemType == KEYMGMT_ITEM_PRIVATEKEY );
assert( keyIDtype == CRYPT_KEYID_NAME );
/* Find the object to delete based on the label. Since we can have
multiple related objects (e.g. a key and a cert) with the same label,
a straight search for all objects with a given label could return
CRYPT_ERROR_DUPLICATE so we search for the objects by type as well as
label. In addition even a search for specific objects can return
CRYPT_ERROR_DUPLICATE so we use the Ex version of findObject() to make
sure we don't get an error if multiple objects exist. Although
cryptlib won't allow more than one object with a given label to be
created, other applications might create duplicate labels. The correct
behaviour in these circumstances is uncertain, what we do for now is
delete the first object we find that matches the label.
First we try for a cert and use that to find associated keys */
cryptStatus = findObjectEx( deviceInfo, &hCertificate, certTemplate, 3 );
if( cryptStatusOK( cryptStatus ) )
{
/* We got a cert, if there are associated keys delete them as well */
cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
CKO_PUBLIC_KEY, &hPubkey );
if( cryptStatusError( cryptStatus ) )
hPubkey = CRYPT_ERROR;
cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
CKO_PRIVATE_KEY, &hPrivkey );
if( cryptStatusError( cryptStatus ) )
hPrivkey = CRYPT_ERROR;
}
else
{
/* We didn't find a cert with the given label, try for public and
private keys */
cryptStatus = findObjectEx( deviceInfo, &hPubkey, keyTemplate, 2 );
if( cryptStatusError( cryptStatus ) )
hPubkey = CRYPT_ERROR;
keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
cryptStatus = findObjectEx( deviceInfo, &hPrivkey, keyTemplate, 2 );
if( cryptStatusError( cryptStatus ) )
hPrivkey = CRYPT_ERROR;
/* There may be an unlabelled cert present, try and find it by
looking for a cert matching the key ID */
if( hPubkey != CRYPT_ERROR || hPrivkey != CRYPT_ERROR )
{
cryptStatus = findObjectFromObject( deviceInfo,
( hPrivkey != CRYPT_ERROR ) ? hPrivkey : hPubkey,
CKO_CERTIFICATE, &hCertificate );
if( cryptStatusError( cryptStatus ) )
hCertificate = CRYPT_ERROR;
}
}
/* If we found a public key with a given label but no private key, try
and find a matching private key by ID, and vice versa */
if( hPubkey != CRYPT_ERROR && hPrivkey == CRYPT_ERROR )
{
cryptStatus = findObjectFromObject( deviceInfo, hPubkey,
CKO_PRIVATE_KEY, &hPrivkey );
if( cryptStatusError( cryptStatus ) )
hPrivkey = CRYPT_ERROR;
}
if( hPrivkey != CRYPT_ERROR && hPubkey == CRYPT_ERROR )
{
cryptStatus = findObjectFromObject( deviceInfo, hPrivkey,
CKO_PUBLIC_KEY, &hPubkey );
if( cryptStatusError( cryptStatus ) )
hPubkey = CRYPT_ERROR;
}
if( hPrivkey == CRYPT_ERROR && hPubkey == CRYPT_ERROR )
return( CRYPT_ERROR_NOTFOUND );
/* Reset the status values, which may contain error values due to not
finding various objects to delete above */
cryptStatus = CRYPT_OK;
status = CKR_OK;
/* Delete the objects */
if( hCertificate != CRYPT_ERROR )
status = C_DestroyObject( cryptoapiInfo->hProv, hCertificate );
if( hPubkey != CRYPT_ERROR )
{
int status2;
status2 = C_DestroyObject( cryptoapiInfo->hProv, hPubkey );
if( status2 != CKR_OK && status == CKR_OK )
status = status2;
}
if( hPrivkey != CRYPT_ERROR )
{
int status2;
status2 = C_DestroyObject( cryptoapiInfo->hProv, hPrivkey );
if( status2 != CKR_OK && status == CKR_OK )
status = status2;
}
if( status != CKR_OK )
cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
return( cryptStatus );
#endif
return( CRYPT_ERROR );
}
/****************************************************************************
* *
* Capability Interface Routines *
* *
****************************************************************************/
#if 0
/* Sign data, check a signature. We use Sign and Verify rather than the
xxxRecover variants because there's no need to use Recover, and because
many implementations don't do Recover */
static int genericSign( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
const CK_MECHANISM *pMechanism,
const void *inBuffer, const int inLength,
void *outBuffer, const int outLength )
{
CK_ULONG resultLen = outLength;
CK_RV status;
status = C_SignInit( cryptoapiInfo->hProv,
( CK_MECHANISM_PTR ) pMechanism,
contextInfoPtr->deviceObject );
if( status == CKR_OK )
status = C_Sign( cryptoapiInfo->hProv, ( CK_BYTE_PTR ) inBuffer,
inLength, outBuffer, &resultLen );
if( status != CKR_OK )
return( mapError( deviceInfo, status, CRYPT_ERROR_FAILED ) );
return( CRYPT_OK );
}
static int genericVerify( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
const CK_MECHANISM *pMechanism,
const void *inBuffer, const int inLength,
void *outBuffer, const int outLength )
{
CK_RV status;
status = C_VerifyInit( cryptoapiInfo->hProv,
( CK_MECHANISM_PTR ) pMechanism,
contextInfoPtr->deviceObject );
if( status == CKR_OK )
status = C_Verify( cryptoapiInfo->hProv, ( CK_BYTE_PTR ) inBuffer,
inLength, outBuffer, outLength );
if( status != CKR_OK )
return( mapError( deviceInfo, status, CRYPT_ERROR_FAILED ) );
return( CRYPT_OK );
}
#endif /* 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -