/* * COPYRIGHT (c) International Business Machines Corp. 2015-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 #include "pkcs11types.h" #include "regress.h" #include "common.c" /* API Routines exercised: * C_GenerateKeyPair */ CK_RV do_GenerateKeyPairRSA(void) { CK_FLAGS flags; CK_SESSION_HANDLE session; CK_RV rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_OBJECT_HANDLE priv_key = CK_INVALID_HANDLE; CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE; CK_MECHANISM mech; CK_KEY_TYPE keytype = CKK_RSA; CK_ULONG modbits = 2048; unsigned int modbytes = modbits / 8; CK_BYTE pubExp[3] = { 0x01, 0x00, 0x01 }; CK_ATTRIBUTE publ_tmpl[] = { {CKA_KEY_TYPE, &keytype, sizeof(keytype)}, {CKA_MODULUS_BITS, &modbits, sizeof(modbits)}, {CKA_PUBLIC_EXPONENT, pubExp, sizeof(pubExp)} }; CK_OBJECT_CLASS class; CK_BYTE publicExponent[4]; CK_BYTE modulus[512]; CK_BYTE subject[20], id[20];; CK_BYTE start_date[20], end_date[20]; CK_BBOOL encrypt, decrypt, sign, sign_recover, verify, verify_recover; CK_BBOOL wrap, unwrap, derive, local, extractable, never; CK_BBOOL sensitive, always; CK_ATTRIBUTE publ_def[] = { {CKA_KEY_TYPE, &keytype, sizeof(keytype)}, {CKA_CLASS, &class, sizeof(class)}, {CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent)}, {CKA_MODULUS, modulus, sizeof(modulus)}, {CKA_SUBJECT, subject, sizeof(subject)}, {CKA_ENCRYPT, &encrypt, sizeof(encrypt)}, {CKA_VERIFY, &verify, sizeof(verify)}, {CKA_VERIFY_RECOVER, &verify_recover, sizeof(verify_recover)}, {CKA_WRAP, &wrap, sizeof(wrap)}, {CKA_ID, &id, sizeof(id)}, {CKA_START_DATE, &start_date, sizeof(start_date)}, {CKA_END_DATE, &end_date, sizeof(end_date)}, {CKA_DERIVE, &derive, sizeof(derive)}, {CKA_LOCAL, &local, sizeof(local)} }; /* According to pkcs#11v2.20, Section 12.1.4, the implementation * MAY contribute some of the CRT attributes. So, dont look for these. * Only check for the common defaults for the private key. */ CK_ATTRIBUTE priv_def[] = { {CKA_KEY_TYPE, &keytype, sizeof(keytype)}, {CKA_CLASS, &class, sizeof(class)}, {CKA_SUBJECT, subject, sizeof(subject)}, {CKA_SENSITIVE, &sensitive, sizeof(sensitive)}, {CKA_DECRYPT, &decrypt, sizeof(decrypt)}, {CKA_SIGN, &sign, sizeof(sign)}, {CKA_SIGN_RECOVER, &sign_recover, sizeof(sign_recover)}, {CKA_UNWRAP, &unwrap, sizeof(unwrap)}, {CKA_EXTRACTABLE, &extractable, sizeof(extractable)}, {CKA_ALWAYS_SENSITIVE, &always, sizeof(always)}, {CKA_NEVER_EXTRACTABLE, &never, sizeof(never)}, {CKA_ID, &id, sizeof(id)}, {CKA_START_DATE, start_date, sizeof(start_date)}, {CKA_END_DATE, end_date, sizeof(end_date)}, {CKA_DERIVE, &derive, sizeof(derive)}, {CKA_LOCAL, &local, sizeof(local)} }; /* Do some setup and login to the token */ testcase_begin("starting..."); testcase_rw_session(); testcase_user_login(); mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; mech.ulParameterLen = 0; mech.pParameter = NULL; /* Assertion #1: generate an RSA key pair. */ testcase_new_assertion(); rc = funcs->C_GenerateKeyPair(session, &mech, publ_tmpl, 3, NULL, 0, &publ_key, &priv_key); if (rc != CKR_OK) { testcase_fail("C_GenerateKeyPair() rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } testcase_pass("C_GenerateKeypair was successful\n"); /* Assertion #2: Ensure public key contains the default attributes * and those the implementation should have contributed for RSA PKCS#1 * key pairs. (Section 12.1.4 of pkcs#11v2.20) */ testcase_new_assertion(); rc = funcs->C_GetAttributeValue(session, publ_key, publ_def, 14); if (rc == CKR_ATTRIBUTE_TYPE_INVALID) { testcase_fail("Some of the default attributes were missing.\n"); goto testcase_cleanup; } if (rc != CKR_OK) { testcase_error("C_GetAttributeValue: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } if (*(CK_ULONG *) publ_def[0].pValue != CKK_RSA) { testcase_fail("Public RSA key was not generated correctly" " (wrong CKA_KEY_TYPE).\n"); } if (*(CK_ULONG *) publ_def[1].pValue != CKO_PUBLIC_KEY) { testcase_fail("Public RSA key was not generated correctly" " (wrong CKA_CLASS).\n"); } if (publ_def[2].ulValueLen != sizeof(pubExp)) { /* some tokens add an leading 0x00 to the exponent value */ unsigned char *pv = (unsigned char *) publ_def[2].pValue; if (publ_def[2].ulValueLen == sizeof(pubExp) + 1 && pv[0] == 0x00 && memcmp(pv + 1, pubExp, sizeof(pubExp)) == 0) { /* len is just +1, first byte is 0, rest matches to pubExp */ } else { testcase_fail("Public RSA key was not generated correctly" " (pub exp mismatch).\n"); } } else { /* same length, check value */ if (memcmp(publ_def[2].pValue, pubExp, sizeof(pubExp)) != 0) { testcase_fail("Public RSA key was not generated correctly" " (pub exp mismatch).\n"); } } if (publ_def[3].ulValueLen != modbytes) { /* some tokens add an leading 0x00 to the modulus value */ unsigned char *pv = (unsigned char *) publ_def[3].pValue; if (publ_def[3].ulValueLen == modbytes + 1 && pv[0] == 0x00) { /* len is just +1, first byte is 0, all fine */ } else { testcase_fail("Public RSA key was not generated correctly" " (modulus length mismatch).\n"); } } testcase_pass("Public RSA key generated correctly.\n"); testcase_new_assertion(); rc = funcs->C_GetAttributeValue(session, priv_key, priv_def, 16); if (rc != CKR_OK) { testcase_error("C_GetAttributeValue: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } if (rc == CKR_ATTRIBUTE_TYPE_INVALID) { testcase_fail("Some of the default attributes were missing.\n"); goto testcase_cleanup; } if (rc != CKR_OK) { testcase_error("C_GetAttributeValue: rc = %s", p11_get_ckr(rc)); goto testcase_cleanup; } /* Assertion #3: Ensure private key contains the default attributes * and those the implementation should have contributed for RSA PKCS#1 * key pairs. (Section 12.1.4 of pkcs#11v2.20) */ if (*(CK_ULONG *) priv_def[0].pValue != CKK_RSA) { testcase_fail("Private RSA key was not generated correctly" " (wrong CKA_KEY_TYPE).\n"); } if (*(CK_ULONG *) priv_def[1].pValue != CKO_PRIVATE_KEY) { testcase_fail("Private RSA key was not generated correctly" " (wrong CKA_CLASS).\n"); } testcase_pass("Private RSA key generated correctly.\n"); testcase_cleanup: funcs->C_DestroyObject(session, priv_key); funcs->C_DestroyObject(session, publ_key); testcase_user_logout(); rc = funcs->C_CloseSession(session); if (rc != CKR_OK) { testcase_error("C_CloseSessions rc=%s", p11_get_ckr(rc)); } return rc; } int main(int argc, char **argv) { int rc; CK_C_INITIALIZE_ARGS cinit_args; CK_RV rv = 0; rc = do_ParseArgs(argc, argv); if (rc != 1) return rc; printf("Using slot #%lu...\n\n", SLOT_ID); printf("With option: nostop: %d\n", no_stop); rc = do_GetFunctionList(); if (!rc) { testcase_error("do_getFunctionList(), rc=%s", p11_get_ckr(rc)); return rc; } memset(&cinit_args, 0x0, sizeof(cinit_args)); cinit_args.flags = CKF_OS_LOCKING_OK; funcs->C_Initialize(&cinit_args); { CK_SESSION_HANDLE hsess = 0; rc = funcs->C_GetFunctionStatus(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL) return rc; rc = funcs->C_CancelFunction(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL) return rc; } testcase_setup(0); rc = do_GenerateKeyPairRSA(); testcase_print_result(); /* make sure we return non-zero if rv is non-zero */ return ((rv == 0) || (rv % 256) ? (int)rv : -1); }