Cryptographic Token Interface Standard |
PKCS#11 |
Cryptoki provides the following functions for key management:
CK_RV C_GenerateKey( CK_SESSION_HANDLE hSession CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey);
C_GenerateKey generates a secret key, creating a new key object.
hSession | is the session's handle; |
pMechanism | points to the key generation mechanism; |
pTemplate | points to the template for the new key; |
ulCount | is the number of attributes in the template; |
phKey | points to the location that receives the handle of the new key. |
If a call to C_GenerateKey cannot support the precise template supplied to it, it will fail and return without creating any key object.
The key object created by a successful call to C_GenerateKey will have its CKA_LOCAL attribute set to TRUE.
CK_SESSION_HANDLE hSession; CK_OBJECT_HANDLE hKey; CK_MECHANISM mechanism = { CKM_DES_KEY_GEN, NULL_PTR, 0 }; CK_RV rv; . . . rv = C_GenerateKey(hSession, &mechanism, NULL_PTR, 0, &hKey); if (rv == CKR_OK) { . . . }
CK_RV C_GenerateKeyPair( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey);
C_GenerateKeyPair generates a public/private key pair, creating new key objects.
hSession | is the session's handle; |
pMechanism | points to the key generation mechanism; |
pPublicKeyTemplate | points to the template for the public key; |
ulPublicKeyAttributeCount | is the number of attributes in the public-key template; |
pPrivateKeyTemplate | points to the template for the private key; |
ulPrivateKeyAttributeCount | is the number of attributes in the private-key template; |
phPublicKey | points to the location that receives the handle of the new public key; |
phPrivateKey | points to the location that receives the handle of the new private key. |
If a call to C_GenerateKeyPair cannot support the precise templates supplied to it, it will fail and return without creating any key objects.
A call to C_GenerateKeyPair will never create just one key and return. A call can fail, and create no keys; or it can succeed, and create a matching public/private key pair.
The key objects created by a successful call to C_GenerateKeyPair will have their CKA_LOCAL attributes set to TRUE.
Note carefully the order of the arguments to C_GenerateKeyPair. The last two arguments do not have the same order as they did in the original Cryptoki Version 1.0 document. The order of these two arguments has caused some unfortunate confusion.
CK_SESSION_HANDLE hSession; CK_OBJECT_HANDLE hPublicKey, hPrivateKey; CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 }; CK_ULONG modulusBits = 768; CK_BYTE publicExponent[] = { 3 }; CK_BYTE subject[] = {...}; CK_BYTE id[] = {123}; CK_BBOOL true = TRUE; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_VERIFY, &true, sizeof(true)}, {CKA_WRAP, &true, sizeof(true)}, {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)}, {CKA_PUBLIC_EXPONENT, publicExponent, sizeof (publicExponent)} }; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_TOKEN, &true, sizeof(true)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_SUBJECT, subject, sizeof(subject)}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_UNWRAP, &true, sizeof(true)} }; CK_RV rv; rv = C_GenerateKeyPair( hSession, &mechanism, publicKeyTemplate, 5, privateKeyTemplate, 8, &hPublicKey, &hPrivateKey); if (rv == CKR_OK) { . . . }
CK_RV C_WrapKey( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen);
C_WrapKey wraps (i.e., encrypts) a private or secret key.
hSession | is the session's handle; |
pMechanism | points to the wrapping mechanism; |
hWrappingKey | is the handle of the wrapping key; hKey is the handle of the key to be wrapped; |
pWrappedKey | points to the location that receives the wrapped key; and pulWrappedKeyLen points to the location that receives the length of the wrapped key. |
The CKA_WRAP attribute of the wrapping key, which indicates whether the key supports wrapping, must be TRUE. The CKA_EXTRACTABLE attribute of the key to be wrapped must also be TRUE.
If the key to be wrapped cannot be wrapped for some token-specific reason, despite its having its CKA_EXTRACTABLE attribute set to TRUE, then C_WrapKey fails with error code CKR_KEY_NOT_WRAPPABLE. If it cannot be wrapped with the specified wrapping key and mechanism solely because of its length, then C_WrapKey fails with error code CKR_KEY_SIZE_RANGE.
C_WrapKey can be used in the following situations:
CK_SESSION_HANDLE hSession; CK_OBJECT_HANDLE hWrappingKey, hKey; CK_MECHANISM mechanism = { CKM_DES3_ECB, NULL_PTR, 0 }; CK_BYTE wrappedKey[8]; CK_ULONG ulWrappedKeyLen; CK_RV rv; . . . ulWrappedKeyLen = sizeof(wrappedKey); rv = C_WrapKey( hSession, &mechanism, hWrappingKey, hKey, wrappedKey, &ulWrappedKeyLen); if (rv == CKR_OK) { . . . }
CK_RV C_UnwrapKey( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
C_UnwrapKey unwraps (i.e. decrypts) a wrapped key, creating a new private key or secret key object.
hSession | is the session's handle; |
pMechanism | points to the unwrapping mechanism; |
hUnwrappingKey | is the handle of the unwrapping key; pWrappedKey points to the wrapped key; |
ulWrappedKeyLen | is the length of the wrapped key; |
pTemplate | points to the template for the new key; |
ulAttributeCount | is the number of attributes in the template; |
phKey | points to the location that receives the handle of the recovered key. |
The new key will have the CKA_ALWAYS_SENSITIVE attribute set to FALSE, and the CKA_EXTRACTABLE attribute set to TRUE.
When C_UnwrapKey is used to unwrap a key with the CKM_KEY_WRAP_SET_OAEP mechanism (see Section 12.32.1), additional "extra data" is decrypted at the same time that the key is unwrapped. The return of this data follows the convention in Section 11.2 on producing output. If the extra data is not returned from a call to C_UnwrapKey (either because the call was only to find out how large the extra data is, or because the buffer provided for the extra data was too small), then C_UnwrapKey will not create a new key, either.
If a call to C_UnwrapKey cannot support the precise template supplied to it, it will fail and return without creating any key object.
The key object created by a successful call to C_UnwrapKey will have its CKA_LOCAL attribute set to FALSE.
CK_SESSION_HANDLE hSession; CK_OBJECT_HANDLE hUnwrappingKey, hKey; CK_MECHANISM mechanism = { CKM_DES3_ECB, NULL_PTR, 0 }; CK_BYTE wrappedKey[8] = {...}; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_DES; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)} }; CK_RV rv; . . . rv = C_UnwrapKey( hSession, &mechanism, hUnwrappingKey, wrappedKey, sizeof(wrappedKey), template, 4, &hKey); if (rv == CKR_OK) { . . . }
CK_RV C_DeriveKey( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
C_DeriveKey derives a key from a base key, creating a new key object.
hSession | is the session's handle; |
pMechanism | points to a structure that specifies the key derivation mechanism; |
hBaseKey | is the handle of the base key; |
pTemplate | points to the template for the new key; |
ulAttributeCount | is the number of attributes in the template; |
phKey | points to the location that receives the handle of the derived key. |
If a call to C_DeriveKey cannot support the precise template supplied to it, it will fail and return without creating any key object.
The key object created by a successful call to C_DeriveKey will have its CKA_LOCAL attribute set to FALSE.
CK_SESSION_HANDLE hSession; CK_OBJECT_HANDLE hPublicKey, hPrivateKey, hKey; CK_MECHANISM keyPairMechanism = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 }; CK_BYTE prime[] = {...}; CK_BYTE base[] = {...}; CK_BYTE publicValue[128]; CK_BYTE otherPublicValue[128]; CK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, otherPublicValue, sizeof(otherPublicValue) }; CK_ATTRIBUTE pTemplate[] = { CKA_VALUE, &publicValue, sizeof(publicValue)} }; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_DES; CK_BBOOL true = TRUE; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_PRIME, prime, sizeof(prime)}, {CKA_BASE, base, sizeof(base)} }; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_DERIVE, &true, sizeof(true)} }; CK_ATTRIBUTE template[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)} }; CK_RV rv; . . . rv = C_GenerateKeyPair( hSession, &keyPairMechanism, publicKeyTemplate, 2, privateKeyTemplate, 1, &hPublicKey, &hPrivateKey); if (rv == CKR_OK) { rv = C_GetAttributeValue(hSession, hPublicKey, &pTemplate, 1); if (rv == CKR_OK) { /* Put other guy's public value in otherPublicValue */ . . . rv = C_DeriveKey( hSession, &mechanism, hPrivateKey, template, 4, &hKey); if (rv == CKR_OK) { . . . } } }