/* * COPYRIGHT (c) International Business Machines Corp. 2006-2017 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this * software constitutes recipient's acceptance of CPL-1.0 terms which can be * found in the file LICENSE file or at * https://opensource.org/licenses/cpl1.0.php */ #include #include #include #include #include "pkcs11types.h" #include "regress.h" CK_FUNCTION_LIST *funcs; CK_FUNCTION_LIST_3_0 *funcs3; CK_INTERFACE *ifs; CK_SLOT_ID SLOT_ID; CK_BBOOL skip_token_obj; CK_BBOOL no_stop; CK_BBOOL no_init; CK_BBOOL securekey; CK_ULONG t_total = 0; // total test assertions CK_ULONG t_ran = 0; // number of assertions ran CK_ULONG t_passed = 0; // number of assertions passed CK_ULONG t_failed = 0; // number of assertions failed CK_ULONG t_skipped = 0; // number of assertions skipped CK_ULONG t_errors = 0; // number of errors #define MAX_MODEL 4 #define DES_KEY_SIZE 8 #define DES3_KEY_SIZE 24 static void *pkcs11lib = NULL; static void unload_pkcslib(void) { if (pkcs11lib != NULL) { dlclose(pkcs11lib); } } static void free_ifs(void) { free(ifs); ifs = NULL; } int mech_supported(CK_SLOT_ID slot_id, CK_ULONG mechanism) { CK_MECHANISM_INFO mech_info; int rc; rc = funcs->C_GetMechanismInfo(slot_id, mechanism, &mech_info); return (rc == CKR_OK); } int mech_supported_flags(CK_SLOT_ID slot_id, CK_ULONG mechanism, CK_FLAGS flags) { CK_MECHANISM_INFO mech_info; int rc; rc = funcs->C_GetMechanismInfo(slot_id, mechanism, &mech_info); if (rc != CKR_OK) return FALSE; if (mech_info.flags & flags) return TRUE; return FALSE; } /* * Check if the specified key size is in the supported range of the mechanism. * * ATTENTION: It is mechanism dependent if the key size is in bits or bytes. * The caller of this function must take care that the keylen parameter is * specified in the appropriate unit. */ int check_supp_keysize(CK_SLOT_ID slot_id, CK_ULONG mechanism, CK_ULONG keylen) { CK_MECHANISM_INFO mech_info; int rc; rc = funcs->C_GetMechanismInfo(slot_id, mechanism, &mech_info); if (rc != CKR_OK) return FALSE; return ((mech_info.ulMinKeySize <= keylen) && (keylen <= mech_info.ulMaxKeySize)); } /** Returns true if and only if slot supports key wrapping with specified mechanism **/ int wrap_supported(CK_SLOT_ID slot_id, CK_MECHANISM mech) { CK_MECHANISM_INFO mech_info; CK_RV rc; // get mech info rc = funcs->C_GetMechanismInfo(slot_id, mech.mechanism, &mech_info); if (rc != CKR_OK) { testcase_error("C_GetMechanismInfo(), rc=%s.", p11_get_ckr(rc)); return -1; } rc = mech_info.flags & CKF_WRAP; return rc; } /** Returns true if and only if slot supports key unwrapping with specified mechanism **/ int unwrap_supported(CK_SLOT_ID slot_id, CK_MECHANISM mech) { CK_MECHANISM_INFO mech_info; CK_RV rc; // get mech info rc = funcs->C_GetMechanismInfo(slot_id, mech.mechanism, &mech_info); if (rc != CKR_OK) { testcase_error("C_GetMechanismInfo(), rc=%s.", p11_get_ckr(rc)); return -1; } rc = mech_info.flags & CKF_UNWRAP; return rc; } /** Create an AES key handle with given value **/ int create_AESKey(CK_SESSION_HANDLE session, unsigned char key[], unsigned char key_len, CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_AES; CK_ATTRIBUTE keyTemplate[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, key, key_len} }; rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); return rc; } /** Generate an AES key handle **/ int generate_AESKey(CK_SESSION_HANDLE session, CK_ULONG key_len, CK_MECHANISM * mechkey, CK_OBJECT_HANDLE * h_key) { CK_ATTRIBUTE key_gen_tmpl[] = { {CKA_VALUE_LEN, &key_len, sizeof(CK_ULONG)} }; CK_RV rc = funcs->C_GenerateKey(session, mechkey, key_gen_tmpl, 1, h_key); return rc; } /** Create a DES key handle with given value **/ int create_DESKey(CK_SESSION_HANDLE session, unsigned char key[], unsigned char klen, CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_DES; CK_BYTE value[DES_KEY_SIZE]; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_ATTRIBUTE keyTemplate[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, value, klen} }; memset(value, 0, sizeof(value)); memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create DES2 key handle with given value **/ int create_DES2Key(CK_SESSION_HANDLE session, unsigned char key[], unsigned char klen, CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_DES2; CK_BYTE value[2 * DES_KEY_SIZE]; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_ATTRIBUTE keyTemplate[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, value, klen} }; memset(value, 0, sizeof(value)); memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create DES3 key handle with given value **/ int create_DES3Key(CK_SESSION_HANDLE session, unsigned char key[], unsigned char klen, CK_OBJECT_HANDLE * h_key) { CK_RV rc; CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; CK_KEY_TYPE keyType = CKK_DES3; CK_BYTE value[DES3_KEY_SIZE]; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_ATTRIBUTE keyTemplate[] = { {CKA_CLASS, &keyClass, sizeof(keyClass)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, value, klen} }; memset(value, 0, sizeof(value)); memcpy(value, key, klen); rc = funcs->C_CreateObject(session, keyTemplate, 5, h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create Generic Secret key handle with given value **/ int create_GenericSecretKey(CK_SESSION_HANDLE session, CK_BYTE key[], CK_ULONG key_len, CK_OBJECT_HANDLE * h_key) { CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; CK_BBOOL false = FALSE; CK_RV rc; CK_ATTRIBUTE key_attribs[] = { {CKA_CLASS, &key_class, sizeof(key_class)}, {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_VALUE, key, key_len} }; rc = funcs->C_CreateObject(session, key_attribs, 4, h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an RSA private key using ctr (chinese remainder theorem) values **/ CK_RV create_RSAPrivateKey(CK_SESSION_HANDLE session, CK_BYTE modulus[], CK_BYTE publicExponent[], CK_BYTE privateExponent[], CK_BYTE prime1[], CK_BYTE prime2[], CK_BYTE exponent1[], CK_BYTE exponent2[], CK_BYTE coefficient[], CK_ULONG modulus_len, CK_ULONG publicExponent_len, CK_ULONG privateExponent_len, CK_ULONG prime1_len, CK_ULONG prime2_len, CK_ULONG exponent1_len, CK_ULONG exponent2_len, CK_ULONG coefficient_len, CK_OBJECT_HANDLE * priv_key) { CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_UTF8CHAR label[] = "An RSA private key object"; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_RV rc; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label) - 1}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_MODULUS, modulus, modulus_len}, {CKA_PUBLIC_EXPONENT, publicExponent, publicExponent_len}, {CKA_PRIVATE_EXPONENT, privateExponent, privateExponent_len}, {CKA_PRIME_1, prime1, prime1_len}, {CKA_PRIME_2, prime2, prime2_len}, {CKA_EXPONENT_1, exponent1, exponent1_len}, {CKA_EXPONENT_2, exponent2, exponent2_len}, {CKA_COEFFICIENT, coefficient, coefficient_len} }; // create key rc = funcs->C_CreateObject(session, template, 17, priv_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an RSA public key **/ CK_RV create_RSAPublicKey(CK_SESSION_HANDLE session, CK_BYTE modulus[], CK_BYTE publicExponent[], CK_ULONG modulus_len, CK_ULONG publicExponent_len, CK_OBJECT_HANDLE * publ_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_UTF8CHAR label[] = "An RSA public key object"; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label) - 1}, {CKA_WRAP, &true, sizeof(true)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_MODULUS, modulus, modulus_len}, {CKA_PUBLIC_EXPONENT, publicExponent, publicExponent_len} }; // create key rc = funcs->C_CreateObject(session, template, 8, publ_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Generate an RSA (PKCS) key pair **/ CK_RV generate_RSA_PKCS_KeyPair(CK_SESSION_HANDLE session, CK_ULONG modulusBits, CK_BYTE publicExponent[], CK_ULONG publicExponent_len, CK_OBJECT_HANDLE * publ_key, CK_OBJECT_HANDLE * priv_key) { CK_RV rc; CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; CK_BYTE subject[] = {0}; 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, publicExponent_len} }; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_TOKEN, &true, sizeof(true)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_SUBJECT, subject, 0}, {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)}, }; // generate keys rc = funcs->C_GenerateKeyPair(session, &mech, publicKeyTemplate, 5, privateKeyTemplate, 8, publ_key, priv_key); return rc; // no error checking due to // ICA Token + public exponent values + CKR_TEMPLATE_INCONSISTENT // work around // see rsa_func.c } /** Generate an EC key pair **/ CK_RV generate_EC_KeyPair(CK_SESSION_HANDLE session, CK_BYTE* ec_params, CK_ULONG ec_params_len, CK_OBJECT_HANDLE * publ_key, CK_OBJECT_HANDLE * priv_key) { CK_RV rc; CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 }; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_BBOOL true = TRUE; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_VERIFY, &true, sizeof(true)}, {CKA_EC_PARAMS, ec_params, ec_params_len}, }; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_TOKEN, &true, sizeof(true)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_DERIVE, &true, sizeof(true)}, }; CK_ULONG num_publ_attrs = sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE); CK_ULONG num_priv_attrs = sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE); // generate keys rc = funcs->C_GenerateKeyPair(session, &mech, publicKeyTemplate, num_publ_attrs, privateKeyTemplate, num_priv_attrs, publ_key, priv_key); return rc; } /** Create an EC private key using private value 'd' and ec parameter values (alg id of curve) **/ CK_RV create_ECPrivateKey(CK_SESSION_HANDLE session, CK_BYTE params[], CK_ULONG params_len, CK_BYTE privatekey[], CK_ULONG privatekey_len, CK_BYTE pubkey[], CK_ULONG pubkey_len, CK_OBJECT_HANDLE * priv_key) { CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_EC; CK_UTF8CHAR label[] = "An EC private key object"; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_RV rc; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_DERIVE, &true, sizeof(true)}, {CKA_EC_PARAMS, params, params_len}, {CKA_EC_POINT, pubkey, pubkey_len}, {CKA_VALUE, privatekey, privatekey_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); return rc; } /** Create an EC public key using ec params and point 'Q' **/ CK_RV create_ECPublicKey(CK_SESSION_HANDLE session, CK_BYTE params[], CK_ULONG params_len, CK_BYTE pointq[], CK_ULONG pointq_len, CK_OBJECT_HANDLE * publ_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_EC; CK_UTF8CHAR label[] = "An EC public key object"; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_VERIFY, &true, sizeof(true)}, {CKA_DERIVE, &true, sizeof(true)}, {CKA_EC_PARAMS, params, params_len}, {CKA_EC_POINT, pointq, pointq_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); return rc; } /** Create an IBM Dilithium private key using private values **/ CK_RV create_DilithiumPrivateKey(CK_SESSION_HANDLE session, CK_BYTE rho[], CK_ULONG rho_len, CK_BYTE seed[], CK_ULONG seed_len, CK_BYTE tr[], CK_ULONG tr_len, CK_BYTE s1[], CK_ULONG s1_len, CK_BYTE s2[], CK_ULONG s2_len, CK_BYTE t0[], CK_ULONG t0_len, CK_BYTE t1[], CK_ULONG t1_len, CK_OBJECT_HANDLE * priv_key) { CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_IBM_PQC_DILITHIUM; CK_UTF8CHAR label[] = "A Dilithium private key object"; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_ULONG keyform = IBM_DILITHIUM_KEYFORM_ROUND2; CK_RV rc; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_PRIVATE, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_IBM_DILITHIUM_RHO, rho, rho_len}, {CKA_IBM_DILITHIUM_SEED, seed, seed_len}, {CKA_IBM_DILITHIUM_TR, tr, tr_len}, {CKA_IBM_DILITHIUM_S1, s1, s1_len}, {CKA_IBM_DILITHIUM_S2, s2, s2_len}, {CKA_IBM_DILITHIUM_T0, t0, t0_len}, {CKA_IBM_DILITHIUM_T1, t1, t1_len}, {CKA_IBM_DILITHIUM_KEYFORM, &keyform, sizeof(keyform)}, }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an IBM Dilithium public key using (rho, t1) **/ CK_RV create_DilithiumPublicKey(CK_SESSION_HANDLE session, CK_BYTE rho[], CK_ULONG rho_len, CK_BYTE t1[], CK_ULONG t1_len, CK_OBJECT_HANDLE * publ_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_IBM_PQC_DILITHIUM; CK_UTF8CHAR label[] = "A Dilithium public key object"; CK_BBOOL true = TRUE; CK_ULONG keyform = IBM_DILITHIUM_KEYFORM_ROUND2; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_VERIFY, &true, sizeof(true)}, {CKA_IBM_DILITHIUM_RHO, rho, rho_len}, {CKA_IBM_DILITHIUM_T1, t1, t1_len}, {CKA_IBM_DILITHIUM_KEYFORM, &keyform, sizeof(keyform)}, }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an DSA public key using the prime 'p', subprime 'q', base 'g' and private value 'y' **/ CK_RV create_DSAPrivateKey(CK_SESSION_HANDLE session, CK_BYTE prime[], CK_ULONG prime_len, CK_BYTE subprime[], CK_ULONG subprime_len, CK_BYTE base[], CK_ULONG base_len, CK_BYTE privatekey[], CK_ULONG privatekey_len, CK_OBJECT_HANDLE * priv_key) { CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_DSA; CK_UTF8CHAR label[] = "An DSA private key object"; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_RV rc; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_PRIME, prime, prime_len}, {CKA_SUBPRIME, subprime, subprime_len}, {CKA_BASE, base, base_len}, {CKA_VALUE, privatekey, privatekey_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an DSA public key using the prime 'p', subprime 'q', base 'g' and public value 'x' **/ CK_RV create_DSAPublicKey(CK_SESSION_HANDLE session, CK_BYTE prime[], CK_ULONG prime_len, CK_BYTE subprime[], CK_ULONG subprime_len, CK_BYTE base[], CK_ULONG base_len, CK_BYTE publickey[], CK_ULONG publickey_len, CK_OBJECT_HANDLE * publ_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_DSA; CK_UTF8CHAR label[] = "An DSA public key object"; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_VERIFY, &true, sizeof(true)}, {CKA_PRIME, prime, prime_len}, {CKA_SUBPRIME, subprime, subprime_len}, {CKA_BASE, base, base_len}, {CKA_VALUE, publickey, publickey_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /** Create an DH public key using the prime 'p', base 'g' and private value 'y' **/ CK_RV create_DHPrivateKey(CK_SESSION_HANDLE session, CK_BYTE prime[], CK_ULONG prime_len, CK_BYTE base[], CK_ULONG base_len, CK_BYTE privatekey[], CK_ULONG privatekey_len, CK_OBJECT_HANDLE * priv_key) { CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_DH; CK_UTF8CHAR label[] = "An DH private key object"; CK_BYTE subject[] = {0}; CK_BYTE id[] = { 123 }; CK_RV rc; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_SUBJECT, subject, 0}, {CKA_ID, id, sizeof(id)}, {CKA_SENSITIVE, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)}, {CKA_SIGN, &true, sizeof(true)}, {CKA_DERIVE, &true, sizeof(true)}, {CKA_PRIME, prime, prime_len}, {CKA_BASE, base, base_len}, {CKA_VALUE, privatekey, privatekey_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), priv_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /* Create an DH public key using the prime 'p', base 'g' and public value 'x' */ CK_RV create_DHPublicKey(CK_SESSION_HANDLE session, CK_BYTE prime[], CK_ULONG prime_len, CK_BYTE base[], CK_ULONG base_len, CK_BYTE publickey[], CK_ULONG publickey_len, CK_OBJECT_HANDLE * publ_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_DH; CK_UTF8CHAR label[] = "An DH public key object"; CK_BBOOL true = TRUE; CK_ATTRIBUTE template[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_KEY_TYPE, &keyType, sizeof(keyType)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, label, sizeof(label)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_VERIFY, &true, sizeof(true)}, {CKA_PRIME, prime, prime_len}, {CKA_BASE, base, base_len}, {CKA_VALUE, publickey, publickey_len} }; // create key rc = funcs->C_CreateObject(session, template, sizeof(template) / sizeof(CK_ATTRIBUTE), publ_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); } return rc; } /* Generate a secret key */ CK_RV generate_SecretKey(CK_SESSION_HANDLE session, CK_ULONG keylen, CK_MECHANISM * mech, CK_OBJECT_HANDLE * secret_key) { CK_RV rc; CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_ATTRIBUTE secret_tmpl[] = { {CKA_CLASS, &class, sizeof(class)}, {CKA_VALUE_LEN, &keylen, sizeof(keylen)} }; rc = funcs->C_GenerateKey(session, mech, secret_tmpl, 2, secret_key); if (rc != CKR_OK) { testcase_fail("C_GenerateKey, rc=%s", p11_get_ckr(rc)); } return rc; } int keysize_supported(CK_SLOT_ID slot_id, CK_ULONG mechanism, CK_ULONG size) { CK_MECHANISM_INFO mech_info; CK_RV rc; rc = funcs->C_GetMechanismInfo(slot_id, mechanism, &mech_info); if (size < mech_info.ulMinKeySize || size > mech_info.ulMaxKeySize) return 0; return (rc == CKR_OK); } /** Returns true if pubexp is valid for EP11 Tokens **/ int is_valid_ep11_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len) { CK_ULONG i; /* everything > 0x10 valid */ if (pubexp[0] > 0x10) { return 1; } else { for (i = 1; i < pubexp_len + 1; i++) { if (pubexp[i] != 0) return 1; } } return 0; } /** Returns true if slot_id is an ICA Token **/ int is_ep11_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; return strstr((const char *) tokinfo.model, "EP11") != NULL; } /** Returns true if pubexp is valid for CCA Tokens **/ int is_valid_cca_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len) { CK_BYTE exp3[] = { 0x03 }; // 3 CK_BYTE exp65537[] = { 0x01, 0x00, 0x01 }; // 65537 return (pubexp_len == 1 && (!memcmp(pubexp, exp3, 1))) || (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3))); } /** Returns true if slot_id is an ICSF token ** ICSF token info is not necessarily hard-coded like the other tokens ** so there is no single identifying attribute. So, instead just ** use logical deduction.... **/ int is_icsf_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; if ((strstr((const char *) tokinfo.model, "ICA") == NULL) && (strstr((const char *) tokinfo.model, "EP11") == NULL) && (strstr((const char *) tokinfo.model, "CCA") == NULL) && (strstr((const char *) tokinfo.model, "Soft") == NULL) && (strstr((const char *) tokinfo.model, "TPM") == NULL)) return TRUE; return FALSE; } /** Returns true if pubexp is valid for ICSF token **/ int is_valid_icsf_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len) { CK_BYTE exp65537[] = { 0x01, 0x00, 0x01 }; // 65537 return (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3))); } /** Returns true if slot_id is an ICA Token **/ int is_ica_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; return strstr((const char *) tokinfo.model, "ICA") != NULL; } /** Returns true if slot_id is a CCA Token **/ int is_cca_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; return strstr((const char *) tokinfo.model, "CCA") != NULL; } /** Returns true if slot_id is a Soft Token **/ int is_soft_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; return strstr((const char *) tokinfo.model, "Soft") != NULL; } /** Returns true if slot_id is a TPM Token **/ int is_tpm_token(CK_SLOT_ID slot_id) { CK_RV rc; CK_TOKEN_INFO tokinfo; rc = funcs->C_GetTokenInfo(slot_id, &tokinfo); if (rc != CKR_OK) return FALSE; return strstr((const char *) tokinfo.model, "TPM") != NULL; } /** Returns true if pubexp is valid for CCA Tokens **/ int is_valid_tpm_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len) { CK_BYTE exp65537[] = { 0x01, 0x00, 0x01 }; // 65537 return (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3))); } int is_valid_tpm_modbits(CK_ULONG modbits) { switch (modbits) { case 512: case 1024: case 2048: return 1; default: return 0; } } int get_so_pin(CK_BYTE * dest) { char *val; val = getenv(PKCS11_SO_PIN_ENV_VAR); if (val == NULL) { fprintf(stderr, "The environment variable %s must be set " "before this testcase is run.\n", PKCS11_SO_PIN_ENV_VAR); return -1; } if ((strlen(val) + 1) > PKCS11_MAX_PIN_LEN) { fprintf(stderr, "The environment variable %s must hold a " "value less than %d chars in length.\n", PKCS11_SO_PIN_ENV_VAR, (int) PKCS11_MAX_PIN_LEN); return -1; } memcpy(dest, val, strlen(val) + 1); return 0; } int get_user_pin(CK_BYTE * dest) { char *val; val = getenv(PKCS11_USER_PIN_ENV_VAR); if (val == NULL) { fprintf(stderr, "The environment variable %s must be set " "before this testcase is run.\n", PKCS11_USER_PIN_ENV_VAR); return -1; } if ((strlen(val) + 1) > PKCS11_MAX_PIN_LEN) { fprintf(stderr, "The environment variable %s must hold a " "value less than %d chars in length.\n", PKCS11_SO_PIN_ENV_VAR, (int) PKCS11_MAX_PIN_LEN); return -1; } memcpy(dest, val, strlen(val) + 1); return 0; } void process_time(SYSTEMTIME t1, SYSTEMTIME t2) { long ms = (t2.tv_usec - t1.tv_usec) / 1000; long s = t2.tv_sec - t1.tv_sec; while (ms < 0) { ms += 1000; s--; } ms += (s * 1000); printf("Time: %u msec\n", (unsigned int) ms); } // // void print_hex(CK_BYTE * buf, CK_ULONG len) { CK_ULONG i, j; i = 0; while (i < len) { for (j = 0; (j < 16) && (i < len); j++, i++) fprintf(stderr, "%02x ", buf[i]); fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } void usage(char *fct) { printf("usage: %s [-securekey] [-noskip] [-noinit] [-h] -slot \n\n", fct); return; } int do_ParseArgs(int argc, char **argv) { int i; char *endp; skip_token_obj = TRUE; no_stop = FALSE; no_init = FALSE; securekey = FALSE; SLOT_ID = 1000; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { usage(argv[0]); return 0; } else if (strcmp(argv[i], "-noskip") == 0) { skip_token_obj = FALSE; } else if (strcmp(argv[i], "-slot") == 0) { if (argc <= i + 1) { printf("No slot number specified\n"); usage(argv[0]); return -1; } SLOT_ID = strtol(argv[i + 1], &endp, 10); if (*endp != '\0') { printf("Invalid slot number specified: %s\n", argv[i + 1]); usage(argv[0]); return -1; } i++; } else if (strcmp(argv[i], "-securekey") == 0) { securekey = TRUE; } else if (strcmp(argv[i], "-noinit") == 0) { no_init = TRUE; } else if (strcmp(argv[i], "-nostop") == 0) { no_stop = TRUE; } else { printf("Invalid argument passed as option: %s\n", argv[i]); usage(argv[0]); return -1; } } // error if slot has not been identified. if (SLOT_ID == 1000) { printf("Please specify the slot to be tested.\n"); usage(argv[0]); return -1; } return 1; } // // CK_BBOOL do_GetFunctionList(void) { CK_INTERFACE *interface; CK_VERSION version; CK_FLAGS flags; CK_BBOOL rv; CK_RV rc; CK_RV(*pfoo) (); char *e; char *f = "libopencryptoki.so"; CK_ULONG nmemb = 0; rv = FALSE; e = getenv("PKCSLIB"); if (e == NULL) e = f; pkcs11lib = dlopen(e, RTLD_NOW); if (pkcs11lib == NULL) goto ret; *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetFunctionList"); if (pfoo == NULL) goto ret; rc = pfoo(&funcs); if (rc != CKR_OK) { testcase_error("C_GetFunctionList rc=%s", p11_get_ckr(rc)); goto ret; } *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetInterfaceList"); if (pfoo == NULL) { goto ret; } rc = pfoo(NULL, &nmemb); if (rc != CKR_OK) { testcase_error("C_GetInterfaceList rc=%s", p11_get_ckr(rc)); goto ret; } ifs = calloc(nmemb, sizeof(*ifs)); if (ifs == NULL) { goto ret; } rc = pfoo(ifs, &nmemb); if (rc != CKR_OK) { testcase_error("C_GetInterfaceList rc=%s", p11_get_ckr(rc)); goto ret; } *(void **)(&pfoo) = dlsym(pkcs11lib, "C_GetInterface"); if (pfoo == NULL) { goto ret; } version.major = 0x03; version.minor = 0x00; flags = CKF_INTERFACE_FORK_SAFE; rc = pfoo((CK_UTF8CHAR *)"PKCS 11", &version, &interface, flags); if (rc != CKR_OK) { testcase_error("C_GetInterface rc=%s", p11_get_ckr(rc)); goto ret; } funcs3 = interface->pFunctionList; rv = TRUE; ret: if (rv == TRUE) { atexit(free_ifs); atexit(unload_pkcslib); } else { free(ifs); ifs = NULL; if (pkcs11lib != NULL) { dlclose(pkcs11lib); pkcs11lib = NULL; } } return rv; }