Cryptographic Token Interface Standard

PKCS#11


Manifest constants

The following definitions can be found in the appropriate header file.

Also, refer [PKCS #11-B] for additional definitions.

#define CKK_RSA 0x00000000
#define CKK_DSA 0x00000001
#define CKK_DH 0x00000002
#define CKK_ECDSA 0x00000003
#define CKK_EC 0x00000003
#define CKK_X9_42_DH 0x00000004
#define CKK_GENERIC_SECRET 0x00000010
#define CKK_RC2 0x00000011
#define CKK_RC4 0x00000012
#define CKK_DES 0x00000013
#define CKK_DES2 0x00000014
#define CKK_DES3 0x00000015
#define CKK_CDMF 0x0000001E
#define CKK_AES 0x0000001F
#define CKK_BLOWFISH 0x00000020
#define CKK_TWOFISH 0x00000021
#define CKK_ARIA 0x00000024
#define CKK_CAMELLIA 0x00000025
#define CKK_SEED 0x00000026
#define CKK_MD5_HMAC 0x00000027
#define CKK_SHA_1_HMAC 0x00000028
#define CKK_RIPEMD128_HMAC 0x00000029
#define CKK_RIPEMD160_HMAC 0x0000002A
#define CKK_SHA256_HMAC 0x0000002B
#define CKK_SHA384_HMAC 0x0000002C
#define CKK_SHA512_HMAC 0x0000002D
#define CKK_SHA224_HMAC 0x0000002E
#define CKK_GOSTR3410 0x00000030
#define CKK_GOSTR3411 0x00000031
#define CKK_GOST28147 0x00000032
#define CKK_VENDOR_DEFINED 0x80000000
#define CKC_X_509 0x00000000
#define CKC_X_509_ATTR_CERT 0x00000001
#define CKC_WTLS 0x00000002
#define CKC_VENDOR_DEFINED 0x80000000
#define CKD_NULL                       0x00000001
#define CKD_SHA1_KDF                    0x00000002
#define CKD_SHA1_KDF_ASN1               0x00000003
#define CKD_SHA1_KDF_CONCATENATE 0x00000004
#define CKD_SHA224_KDF 0x00000005
#define CKD_SHA256_KDF 0x00000006
#define CKD_SHA384_KDF 0x00000007
#define CKD_SHA512_KDF 0x00000008
#define CKD_CPDIVERSIFY_KDF 0x00000009
#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
#define CKM_RSA_PKCS 0x00000001
#define CKM_RSA_9796 0x00000002
#define CKM_RSA_X_509 0x00000003
#define CKM_SHA1_RSA_PKCS 0x00000006
#define CKM_RSA_PKCS_OAEP 0x00000009
#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
#define CKM_RSA_X9_31 0x0000000B
#define CKM_SHA1_RSA_X9_31 0x0000000C
#define CKM_RSA_PKCS_PSS 0x0000000D
#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
#define CKM_DSA_KEY_PAIR_GEN 0x00000010
#define CKM_DSA 0x00000011
#define CKM_DSA_SHA1 0x00000012
#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
#define CKM_DH_PKCS_DERIVE 0x00000021
#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
#define CKM_X9_42_DH_DERIVE 0x00000031
#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
#define CKM_X9_42_MQV_DERIVE 0x00000033
#define CKM_SHA256_RSA_PKCS 0x00000040
#define CKM_SHA384_RSA_PKCS 0x00000041
#define CKM_SHA512_RSA_PKCS 0x00000042
#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
#define CKM_RC2_KEY_GEN 0x00000100
#define CKM_DES2_KEY_GEN 0x00000130
#define CKM_DES3_KEY_GEN 0x00000131
#define CKM_DES3_ECB 0x00000132
#define CKM_DES3_CBC 0x00000133
#define CKM_DES3_MAC 0x00000134
#define CKM_DES3_MAC_GENERAL 0x00000135
#define CKM_DES3_CBC_PAD 0x00000136
#define CKM_DES3_CMAC_GENERAL 0x00000137
#define CKM_DES3_CMAC 0x00000138
#define CKM_CDMF_KEY_GEN 0x00000140
#define CKM_CDMF_ECB 0x00000141
#define CKM_CDMF_CBC 0x00000142
#define CKM_CDMF_MAC 0x00000143
#define CKM_CDMF_MAC_GENERAL 0x00000144
#define CKM_CDMF_CBC_PAD 0x00000145
#define CKM_DES_OFB64 0x00000150
#define CKM_DES_OFB8 0x00000151
#define CKM_DES_CFB64 0x00000152
#define CKM_DES_CFB8 0x00000153
#define CKM_SHA_1 0x00000220
#define CKM_SHA_1_HMAC 0x00000221
#define CKM_SHA_1_HMAC_GENERAL 0x00000222
#define CKM_SHA256 0x00000250
#define CKM_SHA256_HMAC 0x00000251
#define CKM_SHA256_HMAC_GENERAL 0x00000252
#define CKM_SHA384 0x00000260
#define CKM_SHA384_HMAC 0x00000261
#define CKM_SHA384_HMAC_GENERAL 0x00000262
#define CKM_SHA512 0x00000270
#define CKM_SHA512_HMAC 0x00000271
#define CKM_SHA512_HMAC_GENERAL 0x00000272
#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
#define CKM_XOR_BASE_AND_DATA 0x00000364
#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
#define CKM_TLS_PRF 0x00000378
#define CKM_SSL3_MD5_MAC 0x00000380
#define CKM_SSL3_SHA1_MAC 0x00000381
#define CKM_MD5_KEY_DERIVATION 0x00000390
#define CKM_MD2_KEY_DERIVATION 0x00000391
#define CKM_SHA1_KEY_DERIVATION 0x00000392
#define CKM_SHA256_KEY_DERIVATION 0x00000393
#define CKM_SHA384_KEY_DERIVATION 0x00000394
#define CKM_SHA512_KEY_DERIVATION 0x00000395
#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
#define CKM_PKCS5_PBKD2 0x000003B0
#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
#define CKM_WTLS_MASTER_KEY_DERVIE_DH_ECC 0x000003D2
#define CKM_WTLS_PRF 0x000003D3
#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
#define CKM_KEY_WRAP_LYNKS 0x00000400
#define CKM_KEY_WRAP_SET_OAEP 0x00000401
#define CKM_CMS_SIG 0x00000500
#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
#define CKM_EC_KEY_PAIR_GEN 0x00001040
#define CKM_ECDSA 0x00001041
#define CKM_ECDSA_SHA1 0x00001042
#define CKM_ECDH1_DERIVE 0x00001050
#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
#define CKM_ECMQV_DERIVE 0x00001052
#define CKM_AES_KEY_GEN 0x00001080
#define CKM_AES_ECB 0x00001081
#define CKM_AES_CBC 0x00001082
#define CKM_AES_MAC 0x00001083
#define CKM_AES_MAC_GENERAL 0x00001084
#define CKM_AES_CBC_PAD 0x00001085
#define CKM_AES_CMAC_GENERAL 0x00001089
#define CKM_AES_CMAC 0x0000108A
#define CKM_BLOWFISH_KEY_GEN 0x00001090
#define CKM_BLOWFISH_CBC 0x00001091
#define CKM_TWOFISH_KEY_GEN 0x00001092
#define CKM_TWOFISH_CBC 0x00001093
#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
#define CKM_DSA_PARAMETER_GEN 0x00002000
#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
#define CKM_SHA224 0x00000255
#define CKM_SHA224_HMAC 0x00000256
#define CKM_SHA224_HMAC_GENERAL 0x00000257
#define CKM_SHA224_RSA_PKCS 0x00000046
#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
#define CKM_SHA224_KEY_DERIVATION 0x00000396
#define CKG_MGF1_SHA224 0x00000005
#define CKM_AES_CTR 0x00001086
#define CKM_AES_CTS 0x00001089
#define CKM_KIP_DERIVE 0x00000510
#define CKM_KIP_WRAP 0x00000511
#define CKM_KIP_MAC 0x00000512
#define CKM_CAMELLIA_KEY_GEN 0x00000550
#define CKM_CAMELLIA_ECB 0x00000551
#define CKM_CAMELLIA_CBC 0x00000552
#define CKM_CAMELLIA_MAC 0x00000553
#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
#define CKM_CAMELLIA_CBC_PAD 0x00000555
#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
#define CKM_ARIA_KEY_GEN 0x00000560
#define CKM_ARIA_ECB 0x00000561
#define CKM_ARIA_CBC 0x00000562
#define CKM_ARIA_MAC 0x00000563
#define CKM_ARIA_MAC_GENERAL 0x00000564
#define CKM_ARIA_CBC_PAD 0x00000565
#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
#define CKM_SEED_KEY_GEN 0x00000650
#define CKM_SEED_ECB 0x00000651
#define CKM_SEED_CBC 0x00000652
#define CKM_SEED_MAC 0x00000653
#define CKM_SEED_MAC_GENERAL 0x00000654
#define CKM_SEED_CBC_PAD 0x00000655
#define CKM_SEED_ECB_ENCRYPT_DATA 0x00000656
#define CKM_SEED_CBC_ENCRYPT_DATA 0x00000657
#define CKM_AES_GCM 0x00001087
#define CKM_AES_CCM 0x00001088
#define CKM_AES_OFB 0x00002104
#define CKM_AES_CFB64 0x00002105
#define CKM_AES_CFB8 0x00002106
#define CKM_AES_CFB128 0x00002107
#define CKM_BLOWFISH_CBC_PAD 0x00001094 
#define CKM_TWOFISH_CBC_PAD 0x00001095
#define CKM_AES_KEY_WRAP 0x00001090
#define CKM_AES_KEY_WRAP_PAD 0x00001091
#define CKM_RSA_PKCS_TPM_1_1 0x00004001
#define CKM_RSA_PKCS_OAEP_TPM_1_1 0x00004002
#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200
#define CKM_GOSTR3410 0x00001201
#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202
#define CKM_GOSTR3410_KEY_WRAP 0x00001203
#define CKM_GOSTR3410_DERIVE 0x00001204
#define CKM_GOSTR3411 0x00001210
#define CKM_GOSTR3411_HMAC 0x00001211
#define CKM_GOST28147_KEY_GEN 0x00001220
#define CKM_GOST28147_ECB 0x00001221
#define CKM_GOST28147 0x00001222
#define CKM_GOST28147_MAC 0x00001223
#define CKM_GOST28147_KEY_WRAP 0x00001224
#define CKA_GOSTR3410_PARAMS 0x00000250
#define CKA_GOSTR3411_PARAMS 0x00000251
#define CKA_GOST28147_PARAMS 0x00000252
#define CKM_VENDOR_DEFINED 0x80000000



  1. ## OTP Definitions
Note: A C or C++ source file in a Cryptoki application or library can define all the types, mechanisms, and other constants described here by including the header file otp-pkcs11.h. When including the otp-pkcs11.h header file, it should be preceded by an inclusion of the top-level Cryptoki header file pkcs11.h, and the source file must also specify the preprocessor directives indicated in Section 8 of Error: Reference source not found[ PKCS #11-B].



  1. ## Object classes
#define CKO_OTP_KEY0x00000008



  1. ## Key types
#define CKK_SECURID0x00000022
#define CKK_HOTP0x00000023
#define CKK_ACTI 0x00000024



  1. ## Mechanisms
#define CKM_SECURID_KEY_GEN 0x00000280
#define CKM_SECURID0x00000282
#define CKM_HOTP_KEY_GEN0x00000290
#define CKM_HOTP0x00000291
#define CKM_ACTI_KEY_GEN 0x000002A0
#define CKM_ACTI 0x000002A1



  1. ## Attributes
#define CKA_OTP_FORMAT 0x00000220
#define CKA_OTP_LENGTH 0x00000221
#define CKA_OTP_TIME_INTERVAL 0x00000222
#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
#define CKA_OTP_TIME_REQUIREMENT 0x00000225
#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
#define CKA_OTP_PIN_REQUIREMENT 0x00000227
#define CKA_OTP_USER_IDENTIFIER 0x0000022A
#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
#define CKA_OTP_SERVICE_LOGO 0x0000022C
#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
#define CKA_OTP_COUNTER 0x0000022E
#define CKA_OTP_TIME 0x0000022F



  1. ## Attribute constants
#define CK_OTP_FORMAT_DECIMAL0
#define CK_OTP_FORMAT_HEXADECIMAL1
#define CK_OTP_FORMAT_ALPHANUMERIC2
#define CK_OTP_FORMAT_BINARY 3
#define CK_OTP_PARAM_IGNORED0
#define CK_OTP_PARAM_OPTIONAL1
#define CK_OTP_PARAM_MANDATORY2



  1. ## Other constants
#define CK_OTP_VALUE0
#define CK_OTP_PIN1
#define CK_OTP_CHALLENGE2
#define CK_OTP_TIME3
#define CK_OTP_COUNTER4
#define CK_OTP_FLAGS5
#define CK_OTP_OUTPUT_LENGTH6
#define CK_OTP_FORMAT 7
#define CKF_NEXT_OTP0x00000001
#define CKF_EXCLUDE_TIME0x00000002
#define CKF_EXCLUDE_COUNTER0x00000004
#define CKF_EXCLUDE_CHALLENGE0x00000008
#define CKF_EXCLUDE_PIN0x00000010
#define CKF_USER_FRIENDLY_OTP 0x00000020



  1. ## Notifications
#define CKN_OTP_CHANGED 1



  1. ## Return values
#define CKR_NEW_PIN_MODE0x000001B0
#define CKR_NEXT_OTP0x000001B1

OTP Example code

## Disclaimer concerning sample code

For the sake of brevity, sample code presented herein is somewhat incomplete. In particular, initial steps needed to create a session with a cryptographic token are not shown, and the error handling is simplified.



  1. ## OTP retrieval
The following sample code snippet illustrates the retrieval of an OTP value from an OTP token using the C_Sign function. The sample demonstrates the generality of the approach described herein and does not include any OTP mechanism-specific knowledge.

CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_RV rv;
CK_SLOT_ID slotId;
CK_OBJECT_CLASS class = CKO_OTP_KEY;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &class, sizeof(class)} };
CK_UTF8CHAR time[] = {...};
/* UTC time value for OTP, or NULL */
CK_UTF8CHAR pin[] = {...};
/* User PIN, or NULL */
CK_BYTE counter[] = {...};
/* Counter value, or NULL */
CK_BYTE challenge[] = {...};
/* Challenge, or NULL */
CK_MECHANISM_TYPE_PTR allowedMechanisms = NULL_PTR;
CK_MECHANISM_INFO mechanismInfo;
CK_MECHANISM mechanism;
CK_ULONG i, ulOTPLen, ulKeyCount, ulChalReq, ulPINReq, ulTimeReq, ulCounterReq;
CK_ATTRIBUTE mechanisms[] = { {CKA_ALLOWED_MECHANISMS, NULL_PTR, 0} };
CK_ATTRIBUTE attributes[] = { 
{CKA_OTP_CHALLENGE_REQUIREMENT, &ulChalReq, sizeof(ulChalReq)},
{CKA_OTP_PIN_REQUIREMENT, &ulPINReq, sizeof(ulPINReq)},
{CKA_OTP_COUNTER_REQUIREMENT, &ulCounterReq, sizeof(ulCounterReq)},
{CKA_OTP_TIME_REQUIREMENT, &ulTimeReq, sizeof(ulTimeReq)} };
CK_OTP_PARAM param[4];
CK_OTP_PARAMS params;
CK_BYTE *pOTP;/* Storage for OTP result */
do {
/* N.B.: Minimal error and memory handling in this
sample code. */
/* Find first OTP key on the token. */
if ((rv = C_FindObjectsInit(hSession, template, 1)) != CKR_OK) {
break;
};
if ((rv = C_FindObjects(hSession, &hKey, 1, &ulKeyCount)) != CKR_OK) {
break;
};
if (ulKeyCount == 0) {
/* No OTP key found */
break;
}
rv = C_FindObjectsFinal(hSession);
/* Find a suitable OTP mechanism. */
if ((rv = C_GetAttributeValue(hSession, hKey, mechanisms, 1)) != CKR_OK) {
break;
};
if ((allowedMechanisms = (CK_MECHANISM_TYPE_PTR) malloc(mechanisms[0].ulValueLen)) == 0) {
break;
};
mechanisms[0].pValue = allowedMechanisms;
if ((rv = C_GetAttributeValue(hSession, hKey, mechanisms, 1)) != CKR_OK) {
break;
};
for (i = 0; i < mechanisms[0].ulValueLen/ sizeof(CK_MECHANISM_TYPE); ++i) {
if ((rv = C_GetMechanismInfo(slotId, allowedMechanisms[i], &mechanismInfo)) == CKR_OK) {
if (mechanismInfo.flags & CKF_SIGN) {
break;
}
}
}
if (i == mechanisms[0].ulValueLen) {
break;
}
mechanism.mechanism = allowedMechanisms[i];
free(allowedMechanisms);
/* Set required mechanism parameters based on
the key attributes. */
if ((rv = C_GetAttributeValue(hSession, hKey, 
attributes, sizeof(attributes) /
sizeof(attributes[0]))) != CKR_OK) {
break;
}
i = 0;
if (ulPINReq == CK_OTP_PARAM_MANDATORY) {
/* PIN value needed. */
param[i].type = CK_OTP_PIN;
param[i].pValue = pin;
param[i++].ulValueLen = sizeof(pin) - 1;
}
if (ulChalReq == CK_OTP_PARAM_MANDATORY) {
/* Challenge neded. */
param[i].type = CK_OTP_CHALLENGE;
param[i].pValue = challenge;
param[i++].ulValueLen = sizeof(challenge);
}
if (ulTimeReq == CK_OTP_PARAM_MANDATORY) {
/* Time needed (would not normally be
the case if token has its own clock). */
param[i].type = CK_OTP_TIME;
param[i].pValue = time;
param[i++].ulValueLen = sizeof(time) -1;
}
if (ulCounterReq == CK_OTP_PARAM_MANDATORY) {
/* Counter value needed (would not normally 
be the case if token has its own counter.*/
param[i].type = CK_OTP_COUNTER;
param[i].pValue = counter;
param[i++].ulValueLen = sizeof(counter);
}
params.pParams = param;
params.ulCount = i;
mechanism.pParameter = &params;
mechanism.ulParameterLen = sizeof(params);
/* Sign to get the OTP value. */
if ((rv = C_SignInit(hSession, &mechanism, hKey))
!= CKR_OK) {
break;
}
/* Get the buffer length needed for the OTP Value
and any associated data. */
if ((rv = C_Sign(hSession, NULL_PTR, 0, NULL_PTR, &ulOTPLen)) != CKR_OK) {
break;
};
if ((pOTP = malloc(ulOTPLen)) == NULL_PTR) {
break;
};
/* Get the actual OTP value and any
associated data. */
if ((rv = C_Sign(hSession, NULL_PTR, 0, pOTP, 
&ulOTPLen)) != CKR_OK) {
break;
}
/* Traverse the returned pOTP here. The actual
OTP value is in CK_OTP_VALUE in pOTP. */
} while (0); 



  1. ## User-friendly mode OTP token
This sample demonstrates an application retrieving a user-friendly OTP value. The code is the same as in A except for the following:

/* Add these variable declarations */
CK_FLAGS flags = CKF_USER_FRIENDLY_OTP;
CK_BBOOL bUserFriendlyMode;
CK_ULONG ulFormat;
/* Replace the declaration of the "attributes" and the 
"param" variables with: */
CK_ATTRIBUTE attributes[] = { 
{CKA_OTP_CHALLENGE_REQUIREMENT, &ulChalReq, 
sizeof(ulChalReq)},
{CKA_OTP_PIN_REQUIREMENT, &ulPINReq, 
sizeof(ulPINReq)},
{CKA_OTP_COUNTER_REQUIREMENT, &ulCounterReq,
sizeof(ulCounterReq)},
{CKA_OTP_TIME_REQUIREMENT, &ulTimeReq,
sizeof(ulTimeReq)},
{CKA_OTP_USER_FRIENDLY_MODE, &bUserFriendlyMode,
sizeof(bUserFriendlyMode)},
{CKA_OTP_FORMAT, &ulFormat,
sizeof(ulFormat)}
};
CK_OTP_PARAM param[5];
/* Replace the assignment of the "pParam" component 
of the "params" variable with: */
if (bUserFriendlyMode == CK_TRUE) {
/* Token supports user-friendly OTPs */
param[i].type = CK_OTP_FLAGS;
param[i].pValue = &flags;
param[i++].ulValueLen = sizeof(CK_FLAGS);
} else if (ulFormat == CK_OTP_FORMAT_BINARY) {
/* Some kind of error since a user-friendly
OTP cannot be returned to an application
that needs it. */
break;
};
params.pParams = param;
/* Further processing is as in B.1. */



  1. ## OTP verification
The following sample code snippet illustrates the verification of an OTP value from an RSA SecurID token, using the C_Verify function. The desired UTC time, if a time is specified, is supplied in the CK_OTP_PARAMS structure, as is the user's PIN.

CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_UTF8CHAR time[] = {...};
/* UTC time value for OTP, or NULL */
CK_UTF8CHAR pin[] = {...};
/* User PIN or NULL (if collected by library) */
CK_OTP_PARAM param[] = {
{CK_OTP_TIME, time, sizeof(time)-1},
{CK_OTP_PIN, pin, sizeof(pin)-1}
};
CK_OTP_PARAMS params = {param, 2};
CK_MECHANISM mechanism = {CKM_SECURID, &params, sizeof(params)};
CK_ULONG ulKeyCount;
CK_RV rv;
CK_BYTE OTP[] = {...};/* Supplied OTP value. */
CK_ULONG ulOTPLen = strlen((CK_CHAR_PTR)OTP);
CK_OBJECT_CLASS class = CKO_OTP_KEY;
CK_KEY_TYPE keyType = CKK_SECURID;
CK_ATTRIBUTE template[] = {
{CKA_CLASS, &class, sizeof(class)},
{CKA_KEY_TYPE, &keyType, sizeof(keyType)},
};
/* Find the RSA SecurID key on the token. */
rv = C_FindObjectsInit(hSession, template, 2);
if (rv == CKR_OK) {
rv = C_FindObjects(hSession, &hKey, 1, &ulKeyCount);
rv = C_FindObjectsFinal(hSession);
}
if ((rv != CKR_OK) || (ulKeyCount == 0)) {
printf(" \nError: unable to find RSA SecurID key on token.\n");
return(rv);
}
rv = C_VerifyInit(hSession, &mechanism, hKey);
if (rv == CKR_OK) {
ulOTPLen = sizeof(OTP);
rv = C_Verify(hSession, NULL_PTR, 0, OTP, ulOTPLen);
}
switch(rv) {

case CKR_OK:

 printf("\nSupplied OTP value verified.\n");
 break;

case CKR_SIGNATURE_INVALID:

 printf("\nSupplied OTP value not verified.\n");
 break;

default:

 printf("\nError:Unable to verify OTP value.\n");
 break;
}
return(rv);

Using PKCS #11 with CT-KIP

A suggested procedure to perform CT-KIP with a cryptographic token through the PKCS #11 interface using the mechanisms defined herein is as follows:

  1. On the client side,

    ## The client selects a suitable slot and token (e.g. through use of the <TokenID> or the <PlatformInfo> element of the CT-KIP trigger message).
## Optionally, a nonce R is generated, e.g. by calling C_SeedRandom and C_GenerateRandom.

## The client sends its first message to the server, potentially including the nonce R.

  1. On the server side,

    ## A nonce RS is generated, e.g. by calling C_SeedRandom and C_GenerateRandom.
## If the server needs to authenticate its first CT-KIP message, and use of CKM_KIP_MAC has been negotiated, it calls C_SignInit with CKM_KIP_MAC as the mechanism followed by a call to C_Sign. In the call to C_SignInit, KAUTH (see 3) shall be the signature key, the hKey parameter in the CK_KIP_PARAMS structure shall be set to NULL_PTR, the pSeed parameter of the CT_KIP_PARAMS structure shall also be set to NULL_PTR and the ulSeedLen parameter shall be set to zero. In the call to C_Sign, the pData parameter shall be set to point to (the concatenation of the nonce R, if received, and) the nonce RS (see 3 for a definition of the variables), and the ulDataLen parameter shall hold the length of the (concatenated) string. The desired length of the MAC shall be specified through the pulSignatureLen parameter as usual.

## The server sends its first message to the client, including RS , the server's public key K (or an identifier for a shared secret key K), and optionally the MAC.

  1. On the client side,

    ## If a MAC was received, it is verified. If the MAC does not verify, or was required but not received, the protocol session ends with a failure.
## If the MAC verified, or was not required and not present, a generic secret key, RC , is generated by calling C_GenerateKey with the CKM_GENERIC_SECRET_KEY_GEN mechanism. The pTemplate attribute shall have CKA_EXTRACTABLE and CKA_SENSITIVE set to CK_TRUE, and should have CKA_ALLOWED_MECHANISMS set to CKM_KIP_DERIVE only.

## The generic secret key RC is wrapped by calling C_WrapKey. If the server's public key is used to wrap RC , and that key is temporary only, then the CKA_EXTRACTABLE attribute of RC shall be set to CK_FALSE once RC has been wrapped and the server's public key is to be destroyed. If a shared secret key is used to wrap RC , and use of the CT-KIP key wrapping algorithm was negotiated, then the CKM_KIP_WRAP mechanism shall be used. The hKey handle in the CK_KIP_PARAMS structure shall be set to NULL_PTR. The pSeed parameter in the CK_KIP_PARAMS structure shall point to the nonce RS provided by the CT-KIP server, and the ulSeedLen parameter shall indicate the length of RS . The hWrappingKey parameter in the call to C_WrapKey shall be set to refer to the wrapping key.

## The client sends its second message to the server, including the wrapped generic secret key RC .

  1. On the server side,

    ## Once the wrapped generic secret key RC has been received, the server calls C_UnwrapKey. If use of the CT-KIP key wrapping algorithm was negotiated, then CKM_KIP_WRAP shall be used to unwrap RC . When calling C_UnwrapKey, the CK_KIP_PARAMS structure shall be set as described in A above. The hUnwrappingKey function parameter shall refer to the shared secret key and the pTemplate function parameter shall have CKA_SENSITIVE set to CK_TRUE, CKA_KEY_TYPE set to CKK_GENERIC_SECRET and should have CKA_ALLOWED_MECHANISMS set to CKM_KIP_DERIVE only. This will return a handle to the generic secret key RC .
## A token key, KTOKEN , is derived from RC by calling C_DeriveKey with the CKM_KIP_DERIVE mechanism, using RC as hBaseKey. The hKey handle in the CK_KIP_PARAMS structure shall refer either to the public key supplied by the CT-KIP server, or alternatively, the shared secret key indicated by the server. The pSeed parameter shall point to the nonce RS provided by the CT-KIP server, and the ulSeedLen parameter shall indicate the length of RS . The pTemplate attribute shall be set in accordance with local policy and as negotiated in the protocol. This will return a handle to the token key, KTOKEN .

## For the server's last CT-KIP message to the client, if use of the CT-KIP MAC algorithm has been negotiated, then the MAC is calculated by calling C_SignInit with the CKM_KIP_MAC mechanism followed by a call to C_Sign. In the call to C_SignInit, KAUTH (see 3) shall be the signature key, the hKey parameter in the CK_KIP_PARAMS structure shall be a handle to the generic secret key RC , the pSeed parameter of the CT_KIP_PARAMS structure shall be set to NULL_PTR, and the ulSeedLen parameter shall be set to zero. In the call to C_Sign, the pData parameter shall be set to NULL_PTR and the ulDataLen parameter shall be set to 0. The desired length of the MAC shall be specified through the pulSignatureLen parameter as usual.

## The server sends its second message to the client, including the MAC.

  1. On the client side,

    ## The MAC is verified in a reciprocal fashion as it was generated by the server. If use of the CKM_KIP_MAC mechanism was negotiated, then in the call to C_VerifyInit, the hKey parameter in the CK_KIP_PARAMS structure shall refer to RC , the pSeed parameter shall be set to NULL_PTR, and ulSeedLen shall be set to 0. The hKey parameter of C_VerifyInit shall refer to KAUTH . In the call to C_Verify, pData shall be set to NULL_PTR, ulDataLen to 0, pSignature to the MAC value received from the server, and ulSignatureLen to the length of the MAC. If the MAC does not verify the protocol session ends with a failure.
## A token key, KTOKEN , is derived from RC by calling C_DeriveKey with the CKM_KIP_DERIVE mechanism, using RC as hBaseKey. The hKey handle in the CK_KIP_PARAMS structure shall be set to NULL_PTR as token policy must dictate use of the same key as was used to wrap RC . The pSeed parameter shall point to the nonce RS provided by the CT-KIP server, and the ulSeedLen parameter shall indicate the length of RS . The pTemplate attribute shall be set in accordance with local policy and as negotiated and expressed in the protocol. In particular, the value of the <KeyID> element in the server's response message may be used as CKA_ID. The call to C_DeriveKey will, if successful, return a handle to KTOKEN .

When KAUTH is the newly generated KTOKEN , the client will need to call C_DeriveKey before calling C_VerifyInit and C_Verify (since the hKey parameter of C_VerifyInit shall refer to KTOKEN ). In this case, the token should not allow KTOKEN to be used for any other operation than the verification of the MAC value until the MAC has successfully been verified.


RSA Security Inc. Public-Key Cryptography Standards - PKCS#11 - v230mechanism1