/* * COPYRIGHT (c) International Business Machines Corp. 2012-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" #include "common.c" #define AES_KEY_SIZE_128 16 /* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock. * C_OpenSession * C_CloseSession * * API Routines exercised that cause stdll to take /var/lock/opencryptoki_stdll * spinlock. * C_CreateObject * C_Login * * 1) create a data object * 2) create a certificate */ CK_RV do_CreateSessionObject(void) { CK_SLOT_ID slot_id; CK_FLAGS flags; CK_SESSION_HANDLE h_session; CK_RV rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_BYTE false = FALSE; CK_OBJECT_HANDLE h_data; CK_OBJECT_CLASS data_class = CKO_DATA; CK_BYTE data_application[] = "Test Application"; CK_BYTE data_value[] = "1234567890abcedfghijklmnopqrstuvwxyz"; CK_ATTRIBUTE data_attribs[] = { {CKA_CLASS, &data_class, sizeof(data_class)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_APPLICATION, &data_application, sizeof(data_application)}, {CKA_VALUE, &data_value, sizeof(data_value)} }; CK_OBJECT_HANDLE h_cert; CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert_type = CKC_X_509; CK_BYTE cert_subject[] = "Certificate subject"; CK_BYTE cert_id[] = "Certificate ID"; CK_BYTE cert_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert_attribs[] = { {CKA_CLASS, &cert_class, sizeof(cert_class)}, {CKA_TOKEN, &false, sizeof(false)}, {CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)}, {CKA_SUBJECT, &cert_subject, sizeof(cert_subject)}, {CKA_ID, &cert_id, sizeof(cert_id)}, {CKA_VALUE, &cert_value, sizeof(cert_value)} }; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); slot_id = SLOT_ID; // create a USER R/W session flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto done; } // now, create the objects rc = funcs->C_CreateObject(h_session, data_attribs, 4, &h_data); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } done: // done...close the session and verify the object is deleted rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_fail("C_CloseAllSessions() rc=%s", p11_get_ckr(rc)); return rc; } testcase_pass("looks okay..."); return rc; } /* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock. * C_OpenSession * C_CloseSession * * API routines exercised that result in stdll taking * /var/lock/opencryptoki_stdll spinlock. * C_CreateObject * C_CopyObject * C_DestroyObject * C_GetAttributeValue * C_GetObjectSize * * 1) create a data object with no CKA_APPLICATION attribute * 2) create a copy of the object specifying the CKA_APPLICATION attribute * 3) extract the CK_VALUE attribute from the copy. Ensure matches the original * 4) extract the CKA_APPLICATION attribute from the original. ensure empty. * 5) extract the CKA_APPLICATION attribute from the copy. ensure is correct. * 6) attempt to extract CK_PRIME from the original. ensure fails correctly. * 7) attempt to extract CK_PRIME from a non-existant object. ensure fails * correctly. * 8) get the size of the original object and copied objects * 9) destroy the original object. ensure this succeeds. * A) destroy a non-existant object. ensure this fails correctly. * B) get the size of the original object. ensure this fails correctly. */ CK_RV do_CopyObject(void) { CK_SLOT_ID slot_id; CK_FLAGS flags; CK_SESSION_HANDLE h_session; CK_RV rc = 0, loc_rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_ULONG obj_size; CK_BYTE true = TRUE; CK_OBJECT_HANDLE h_data; CK_OBJECT_CLASS data_class = CKO_DATA; CK_BYTE data_application[] = "Test Application"; CK_BYTE data_value[] = "1234567890abcedfghijklmnopqrstuvwxyz"; CK_ATTRIBUTE data_attribs[] = { {CKA_CLASS, &data_class, sizeof(data_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_VALUE, &data_value, sizeof(data_value)} }; CK_OBJECT_HANDLE h_copy; CK_ATTRIBUTE copy_attribs[] = { {CKA_APPLICATION, &data_application, sizeof(data_application)} }; CK_BYTE buf1[100]; CK_ATTRIBUTE verify_attribs[] = { {CKA_APPLICATION, &buf1, sizeof(buf1)} }; CK_BYTE buf2[100]; CK_ATTRIBUTE prime_attribs[] = { {CKA_PRIME, &buf2, sizeof(buf2)} }; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); slot_id = SLOT_ID; /* create a USER R/W session */ flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto done; } /* create the object */ rc = funcs->C_CreateObject(h_session, data_attribs, 3, &h_data); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } /* create the copy */ rc = funcs->C_CopyObject(h_session, h_data, copy_attribs, 1, &h_copy); if (rc != CKR_OK) { testcase_fail("C_CopyObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } /* now, try to extract the CKA_APPLICATION attribute from the original * this will pull in the token's default value for CKA_APPLICATION which */ verify_attribs[0].ulValueLen = sizeof(buf1); rc = funcs->C_GetAttributeValue(h_session, h_data, verify_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc)); goto destroy; } /* now, try to extract the CKA_APPLICATION attribute from the copy */ verify_attribs[0].ulValueLen = sizeof(buf1); rc = funcs->C_GetAttributeValue(h_session, h_copy, verify_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_GetAttributeValue() rc=%s", p11_get_ckr(rc)); goto destroy; } if (memcmp(&data_application, verify_attribs[0].pValue, sizeof(data_application)) != 0) { testcase_fail("extracted attribute doesn't match"); rc = -1; goto destroy; } /* now, try to extract CKA_PRIME from the original. * this should not exist */ prime_attribs[0].ulValueLen = sizeof(buf2); rc = funcs->C_GetAttributeValue(h_session, h_data, prime_attribs, 1); if (rc != CKR_ATTRIBUTE_TYPE_INVALID) { testcase_fail("C_GetAttributeValue() rc = %s (expected " "CKR_ATTRIBUTE_TYPE_INVALID)", p11_get_ckr(rc)); goto destroy; } /* now, try to extract CKA_PRIME from a bogus object handle. * this should not exist */ rc = funcs->C_GetAttributeValue(h_session, 98765, prime_attribs, 1); if (rc != CKR_OBJECT_HANDLE_INVALID) { testcase_fail("C_GetAttributeValue() rc = %s (expected " "CKR_OBJECT_HANDLE_INVALID)", p11_get_ckr(rc)); goto destroy; } /* now, get the size of the original object */ rc = funcs->C_GetObjectSize(h_session, h_data, &obj_size); if (rc != CKR_OK) { testcase_fail("C_GetObjectSize() rc = %s", p11_get_ckr(rc)); goto destroy; } testcase_pass("Looks okay..."); destroy: /* now, destroy the original object and the copy */ loc_rc = funcs->C_DestroyObject(h_session, h_copy); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); destroy_1: loc_rc = funcs->C_DestroyObject(h_session, h_data); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); done: loc_rc = funcs->C_CloseAllSessions(slot_id); if (loc_rc != CKR_OK) testcase_error("C_CloseAllSessions() loc_rc=%s", p11_get_ckr(loc_rc)); return rc; } /* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock. * C_OpenSession * C_CloseSession * * API routines exercised that result in stdll taking * /var/lock/opencryptoki_stdll spinlock. * C_CreateObject * C_GetAttributeValue * C_SetAttributeValue * * 1) create a certificate object with no CKA_SERIAL_NUMBER or CKA_ISSUER * 2) add CKA_SERIAL_NUMBER and CKA_ISSUER and modify CKA_ID. * verify this works. * 3) try to modify CKA_VALUE and CKA_ID in a single call to * C_SetAttributeValue. verify that this fails correctly and that * the object is not modified. */ CK_RV do_SetAttributeValues(void) { CK_SLOT_ID slot_id; CK_FLAGS flags; CK_SESSION_HANDLE h_session; CK_RV rc = 0, loc_rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_BYTE true = TRUE; CK_OBJECT_HANDLE h_cert; CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert_type = CKC_X_509; CK_BYTE cert_subject[] = "Certificate subject"; CK_BYTE cert_id[] = "Certificate ID"; CK_BYTE cert_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert_attribs[] = { {CKA_CLASS, &cert_class, sizeof(cert_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)}, {CKA_SUBJECT, &cert_subject, sizeof(cert_subject)}, {CKA_ID, &cert_id, sizeof(cert_id)}, {CKA_VALUE, &cert_value, sizeof(cert_value)} }; CK_BYTE cert_id2[] = "New ID"; CK_BYTE cert_issuer[] = "Certificate Issuer"; CK_BYTE cert_ser_no[] = "Serial Number: 12345"; CK_ATTRIBUTE update_attr[] = { {CKA_SERIAL_NUMBER, &cert_ser_no, sizeof(cert_ser_no)}, {CKA_ISSUER, &cert_issuer, sizeof(cert_issuer)}, {CKA_ID, &cert_id2, sizeof(cert_id2)} }; CK_BYTE cert_value2[] = "Invalid Value"; CK_BYTE cert_id3[] = "ID #3"; CK_ATTRIBUTE invalid_attr[] = { {CKA_VALUE, &cert_value2, sizeof(cert_value2)}, {CKA_ID, &cert_id3, sizeof(cert_id3)} }; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); slot_id = SLOT_ID; /* create a USER R/W session */ flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto error; } /* create the object */ rc = funcs->C_CreateObject(h_session, cert_attribs, 6, &h_cert); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto error; } /* Add CKA_SERIAL_NUMBER and CKA_ISSUER and change the * existing CKA_ID */ rc = funcs->C_SetAttributeValue(h_session, h_cert, update_attr, 3); if (rc != CKR_OK) { testcase_fail("C_SetAttributeValue() rc = %s", p11_get_ckr(rc)); goto done; } else { CK_BYTE buf1[100]; CK_BYTE buf2[100]; CK_BYTE buf3[100]; CK_ATTRIBUTE check1[] = { {CKA_ISSUER, &buf1, sizeof(buf1)}, {CKA_SERIAL_NUMBER, &buf2, sizeof(buf2)}, {CKA_ID, &buf3, sizeof(buf3)} }; rc = funcs->C_GetAttributeValue(h_session, h_cert, (CK_ATTRIBUTE *) & check1, 3); if (rc != CKR_OK) { testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc)); goto done; } if (memcmp(check1[0].pValue, cert_issuer, check1[0].ulValueLen) != 0) { testcase_fail("CKA_ISSUER mismatch"); rc = -1; goto done; } if (memcmp(check1[1].pValue, cert_ser_no, check1[1].ulValueLen) != 0) { testcase_fail("CKA_SERIAL_NUMBER mismatch"); rc = -1; goto done; } if (memcmp(check1[2].pValue, cert_id2, check1[2].ulValueLen) != 0) { testcase_fail("CKA_ID mismatch"); rc = -1; goto done; } } /* the next template tries to update a CK_ID (valid) and * CKA_VALUE (read-only). the entire operation should fail -- no * attributes should get modified */ rc = funcs->C_SetAttributeValue(h_session, h_cert, invalid_attr, 2); if (rc != CKR_ATTRIBUTE_READ_ONLY) { testcase_fail ("C_SetAttributeValue() rc = %s (expected CKR_ATTRIBUTE_READ_ONLY)", p11_get_ckr(rc)); goto done; } else { CK_BYTE buf1[100]; CK_ATTRIBUTE check1[] = { {CKA_ID, &buf1, sizeof(buf1)} }; rc = funcs->C_GetAttributeValue(h_session, h_cert, check1, 1); if (rc != CKR_OK) { testcase_fail("C_GetAttributeValue() rc = %s", p11_get_ckr(rc)); goto done; } if (memcmp(check1[0].pValue, cert_id2, check1[0].ulValueLen) != 0) { testcase_fail("CKA_ID mismatch"); rc = -1; goto done; } } testcase_pass("Looks okay..."); done: /* now destroy the objects but don't clobber rc */ loc_rc = funcs->C_DestroyObject(h_session, h_cert); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); error: /* done...close the session */ loc_rc = funcs->C_CloseAllSessions(slot_id); if (loc_rc != CKR_OK) testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc)); return rc; } /* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock. * C_OpenSession * C_CloseSession * * API routines exercised that result in stdll taking * /var/lock/opencryptoki_stdll spinlock. * C_FindObjectsInit * C_FindObjects * C_CreateObject * * 1) Create 3 certificates with different CKA_ID attributes * 2) Search for a particular CKA_ID. Verify this works. * 3) Search for a non-existant CKA_ID. Verify this returns nothing. * 4) Specify an empty template. Verify that all 3 objects are returned. */ CK_RV do_FindObjects(void) { CK_SLOT_ID slot_id; CK_FLAGS flags; CK_SESSION_HANDLE h_session; CK_RV rc = 0, loc_rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_BYTE true = TRUE; CK_OBJECT_HANDLE h_cert1; CK_OBJECT_CLASS cert1_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert1_type = CKC_X_509; CK_BYTE cert1_subject[] = "Certificate subject #1"; CK_BYTE cert1_id[] = "Certificate ID #1"; CK_BYTE cert1_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert1_attribs[] = { {CKA_CLASS, &cert1_class, sizeof(cert1_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert1_type, sizeof(cert1_type)}, {CKA_SUBJECT, &cert1_subject, sizeof(cert1_subject)}, {CKA_ID, &cert1_id, sizeof(cert1_id)}, {CKA_VALUE, &cert1_value, sizeof(cert1_value)} }; CK_OBJECT_HANDLE h_cert2; CK_OBJECT_CLASS cert2_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert2_type = CKC_X_509; CK_BYTE cert2_subject[] = "Certificate subject #2"; CK_BYTE cert2_id[] = "Certificate ID #2"; CK_BYTE cert2_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert2_attribs[] = { {CKA_CLASS, &cert2_class, sizeof(cert2_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert2_type, sizeof(cert2_type)}, {CKA_SUBJECT, &cert2_subject, sizeof(cert2_subject)}, {CKA_ID, &cert2_id, sizeof(cert2_id)}, {CKA_VALUE, &cert2_value, sizeof(cert2_value)} }; CK_OBJECT_HANDLE h_cert3; CK_OBJECT_CLASS cert3_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert3_type = CKC_X_509; CK_BYTE cert3_subject[] = "Certificate subject #3"; CK_BYTE cert3_id[] = "Certificate ID #3"; CK_BYTE cert3_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert3_attribs[] = { {CKA_CLASS, &cert3_class, sizeof(cert3_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert3_type, sizeof(cert3_type)}, {CKA_SUBJECT, &cert3_subject, sizeof(cert3_subject)}, {CKA_ID, &cert3_id, sizeof(cert3_id)}, {CKA_VALUE, &cert3_value, sizeof(cert3_value)} }; CK_BYTE find1_id[] = "Certificate ID #2"; CK_ATTRIBUTE find1_attribs[] = { {CKA_ID, &find1_id, sizeof(find1_id)} }; CK_BYTE find2_id[] = "Certificate ID #12345"; CK_ATTRIBUTE find2_attribs[] = { {CKA_ID, &find2_id, sizeof(find2_id)} }; CK_OBJECT_HANDLE obj_list[10]; CK_ULONG find_count; unsigned int i; int got_it = 0; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); slot_id = SLOT_ID; /* create a USER R/W session */ flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto done; } /* create the objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 6, &h_cert1); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 6, &h_cert2); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 6, &h_cert3); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } /* now, search for the 2nd objects */ rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } do { rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } /* step through list and find our object handle */ for (i = 0; i < find_count; i++) { if (obj_list[i] == h_cert2) got_it++; } } while (got_it == 0 && find_count != 0); rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } if (got_it == 0) { testcase_fail("could not find object handle"); rc = -1; goto destroy; } /* now, search for a non-existant object */ rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } if (find_count != 0) { testcase_fail("found %ld objects when none where expected", find_count); rc = -1; goto destroy; } testcase_pass("Looks okay..."); destroy: /* now destroy the objects that were created */ loc_rc = funcs->C_DestroyObject(h_session, h_cert3); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); destroy_2: loc_rc = funcs->C_DestroyObject(h_session, h_cert2); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); destroy_1: loc_rc = funcs->C_DestroyObject(h_session, h_cert1); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); done: /* done...close the session */ loc_rc = funcs->C_CloseAllSessions(slot_id); if (loc_rc != CKR_OK) testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc)); return rc; } /* API Routines exercised that take /var/lock/LCK..opencryptoki spinlock. * C_OpenSession * C_CloseSession * * API routines exercised that result in stdll taking * /var/lock/opencryptoki_stdll spinlock. * C_FindObjectsInit * C_FindObjects * C_CreateObject * * 1) Create 3 certificates as PUBLIC token objects * 2) Search for a particular CKA_ID. Verify that this works. * 3) Do FindObjects with a NULL template. Verify that all 3 token objects * are found. * 4) Search for a particular CKA_ID. Verify it works. * 5) Search for a non-existant CKA_ID. Verify it returns nothing. * 6) Close all sessions. Then create a new session. * 7) Search for a particular CKA_ID. Verify it works. * 8) Search for a non-existant CKA_ID. Verify it returns nothing. * 9) Destroy all 3 token objects */ CK_RV do_CreateTokenObjects(void) { unsigned int i; int got_it = 0; CK_SLOT_ID slot_id; CK_FLAGS flags; CK_SESSION_HANDLE h_session; CK_RV rc = 0, loc_rc = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_BYTE true = TRUE; CK_BYTE false = FALSE; CK_OBJECT_HANDLE h_cert1; CK_OBJECT_CLASS cert1_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert1_type = CKC_X_509; CK_BYTE cert1_subject[] = "Certificate subject #1"; CK_BYTE cert1_id[] = "Certificate ID #1"; CK_BYTE cert1_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert1_attribs[] = { {CKA_CLASS, &cert1_class, sizeof(cert1_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert1_type, sizeof(cert1_type)}, {CKA_SUBJECT, &cert1_subject, sizeof(cert1_subject)}, {CKA_ID, &cert1_id, sizeof(cert1_id)}, {CKA_VALUE, &cert1_value, sizeof(cert1_value)}, {CKA_PRIVATE, &false, sizeof(false)} }; CK_OBJECT_HANDLE h_cert2; CK_OBJECT_CLASS cert2_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert2_type = CKC_X_509; CK_BYTE cert2_subject[] = "Certificate subject #2"; CK_BYTE cert2_id[] = "Certificate ID #2"; CK_BYTE cert2_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert2_attribs[] = { {CKA_CLASS, &cert2_class, sizeof(cert2_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert2_type, sizeof(cert2_type)}, {CKA_SUBJECT, &cert2_subject, sizeof(cert2_subject)}, {CKA_ID, &cert2_id, sizeof(cert2_id)}, {CKA_VALUE, &cert2_value, sizeof(cert2_value)}, {CKA_PRIVATE, &false, sizeof(false)} }; CK_OBJECT_HANDLE h_cert3; CK_OBJECT_CLASS cert3_class = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE cert3_type = CKC_X_509; CK_BYTE cert3_subject[] = "Certificate subject #3"; CK_BYTE cert3_id[] = "Certificate ID #3"; CK_BYTE cert3_value[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; CK_ATTRIBUTE cert3_attribs[] = { {CKA_CLASS, &cert3_class, sizeof(cert3_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_CERTIFICATE_TYPE, &cert3_type, sizeof(cert3_type)}, {CKA_SUBJECT, &cert3_subject, sizeof(cert3_subject)}, {CKA_ID, &cert3_id, sizeof(cert3_id)}, {CKA_VALUE, &cert3_value, sizeof(cert3_value)}, {CKA_PRIVATE, &false, sizeof(false)} }; CK_BYTE find1_id[] = "Certificate ID #2"; CK_ATTRIBUTE find1_attribs[] = { {CKA_ID, &find1_id, sizeof(find1_id)} }; CK_BYTE find2_id[] = "Certificate ID #123456"; CK_ATTRIBUTE find2_attribs[] = { {CKA_ID, &find2_id, sizeof(find2_id)} }; CK_OBJECT_HANDLE obj_list[10]; CK_ULONG find_count; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); slot_id = SLOT_ID; /* create a USER R/W session */ flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto done; } /* create the token objects */ rc = funcs->C_CreateObject(h_session, cert1_attribs, 7, &h_cert1); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto done; } rc = funcs->C_CreateObject(h_session, cert2_attribs, 7, &h_cert2); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } rc = funcs->C_CreateObject(h_session, cert3_attribs, 7, &h_cert3); if (rc != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } /* now, search for the 2nd object */ rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } do { rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } /* step through list and find 2nd object's handle */ for (i = 0; i < find_count; i++) { if (obj_list[i] == h_cert2) got_it++; } } while (got_it == 0 && find_count != 0); rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } if (got_it == 0) { testcase_fail("could not find 2nd object's handle"); rc = -1; goto destroy; } /* now, search for a non-existant attribute */ rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } if (find_count != 0) { testcase_fail("found %ld objects when none where expected", find_count); rc = -1; goto destroy; } /* done...close all sessions and open a new one */ rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_fail("C_CloseAllSessions() rc = %s", p11_get_ckr(rc)); goto destroy; } /* create a USER R/W session */ flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; rc = funcs->C_OpenSession(slot_id, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto destroy; } /* now, search for the 2nd object */ rc = funcs->C_FindObjectsInit(h_session, find1_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } do { rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } /* step through list and find 2nd object's handle */ got_it = 0; for (i = 0; i < find_count; i++) { if (obj_list[i] == h_cert2) got_it++; } } while (got_it == 0 && find_count != 0); rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } if (got_it == 0) { testcase_fail("could not find 2nd object's handle in new session"); rc = -1; goto destroy; } /* now, search for a non-existant attribute */ rc = funcs->C_FindObjectsInit(h_session, find2_attribs, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } if (find_count != 0) { testcase_fail("found %ld objects when none where expected", find_count); rc = -1; goto destroy; } rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); goto destroy; } testcase_pass("Looks okay..."); /* Destroy the created objects, don't clobber the rc */ destroy: loc_rc = funcs->C_DestroyObject(h_session, h_cert3); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); destroy_2: loc_rc = funcs->C_DestroyObject(h_session, h_cert2); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); destroy_1: loc_rc = funcs->C_DestroyObject(h_session, h_cert1); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() loc_rc = %s", p11_get_ckr(loc_rc)); done: /* done...close the session */ loc_rc = funcs->C_CloseAllSessions(slot_id); if (loc_rc != CKR_OK) testcase_error("C_CloseAllSessions() loc_rc = %s", p11_get_ckr(loc_rc)); return rc; } /* * do_HW_Feature_Search Test: * * 1. Create 5 objects, 3 of which are HW_FEATURE objects. * 2. Search for objects using a template that does have its * HW_FEATURE attribute set. * 3. Result should be that the hardware feature object is returned. * */ CK_RV do_HWFeatureSearch(void) { unsigned int i, got_it = 0; CK_RV rc, loc_rc; CK_ULONG find_count; CK_SLOT_ID slot_id; CK_BBOOL false = FALSE; CK_BBOOL true = TRUE; CK_SESSION_HANDLE h_session = 0; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN] = {0}; CK_ULONG user_pin_len = 0; /* A counter object */ CK_OBJECT_CLASS counter1_class = CKO_HW_FEATURE; CK_HW_FEATURE_TYPE feature1_type = CKH_MONOTONIC_COUNTER; CK_UTF8CHAR counter1_label[] = "Monotonic counter"; CK_CHAR counter1_value[16]; CK_ATTRIBUTE counter1_template[] = { {CKA_CLASS, &counter1_class, sizeof(counter1_class)}, {CKA_HW_FEATURE_TYPE, &feature1_type, sizeof(feature1_type)}, {CKA_LABEL, counter1_label, sizeof(counter1_label) - 1}, {CKA_VALUE, counter1_value, sizeof(counter1_value)}, {CKA_RESET_ON_INIT, &true, sizeof(true)}, {CKA_HAS_RESET, &false, sizeof(false)} }; /* A clock object */ CK_OBJECT_CLASS clock_class = CKO_HW_FEATURE; CK_HW_FEATURE_TYPE clock_type = CKH_CLOCK; CK_UTF8CHAR clock_label[] = "Clock"; CK_CHAR clock_value[16] = {0}; CK_ATTRIBUTE clock_template[] = { {CKA_CLASS, &clock_class, sizeof(clock_class)}, {CKA_HW_FEATURE_TYPE, &clock_type, sizeof(clock_type)}, {CKA_LABEL, clock_label, sizeof(clock_label) - 1}, {CKA_VALUE, clock_value, sizeof(clock_value)} }; /* A data object */ CK_OBJECT_CLASS obj1_class = CKO_DATA; CK_UTF8CHAR obj1_label[] = "Object 1"; CK_BYTE obj1_data[] = "Object 1's data"; CK_ATTRIBUTE obj1_template[] = { {CKA_CLASS, &obj1_class, sizeof(obj1_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_LABEL, obj1_label, sizeof(obj1_label) - 1}, {CKA_VALUE, obj1_data, sizeof(obj1_data)} }; /* A secret key object */ CK_OBJECT_CLASS obj2_class = CKO_SECRET_KEY; CK_KEY_TYPE obj2_type = CKK_AES; CK_UTF8CHAR obj2_label[] = "Object 2"; CK_BYTE obj2_data[AES_KEY_SIZE_128] = {0}; CK_ATTRIBUTE obj2_template[] = { {CKA_CLASS, &obj2_class, sizeof(obj2_class)}, {CKA_TOKEN, &true, sizeof(true)}, {CKA_KEY_TYPE, &obj2_type, sizeof(obj2_type)}, {CKA_LABEL, obj2_label, sizeof(obj2_label) - 1}, {CKA_VALUE, obj2_data, sizeof(obj2_data)} }; CK_OBJECT_HANDLE h_counter1 = 0, h_clock = 0, h_obj1 = 0, h_obj2 = 0, obj_list[10] = {0}; CK_ATTRIBUTE find_tmpl[] = { {CKA_CLASS, &counter1_class, sizeof(counter1_class)} }; slot_id = SLOT_ID; testcase_begin("starting..."); if (get_user_pin(user_pin)) return CKR_FUNCTION_FAILED; user_pin_len = (CK_ULONG) strlen((char *) user_pin); /* Open a session with the token */ if ((rc = funcs->C_OpenSession(slot_id, (CKF_SERIAL_SESSION | CKF_RW_SESSION), NULL_PTR, NULL_PTR, &h_session)) != CKR_OK) { testcase_fail("C_OpenSession() rc = %s", p11_get_ckr(rc)); return rc; } // Login correctly rc = funcs->C_Login(h_session, CKU_USER, user_pin, user_pin_len); if (rc != CKR_OK) { testcase_fail("C_Login() rc = %s", p11_get_ckr(rc)); goto session_close; } /* Create the 3 test objects */ if ((rc = funcs->C_CreateObject(h_session, obj1_template, 4, &h_obj1)) != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto session_close; } if ((rc = funcs->C_CreateObject(h_session, obj2_template, 5, &h_obj2)) != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_1; } /* try and create a monotonic object. This should fail * since it is a read only feature. */ if ((rc = funcs->C_CreateObject(h_session, counter1_template, 6, &h_counter1)) != CKR_ATTRIBUTE_READ_ONLY) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } if ((rc = funcs->C_CreateObject(h_session, clock_template, 4, &h_clock)) != CKR_OK) { testcase_fail("C_CreateObject() rc = %s", p11_get_ckr(rc)); goto destroy_2; } /* Now find the hardware feature objects */ rc = funcs->C_FindObjectsInit(h_session, find_tmpl, 1); if (rc != CKR_OK) { testcase_fail("C_FindObjectsInit() rc = %s", p11_get_ckr(rc)); goto destroy; } do { rc = funcs->C_FindObjects(h_session, obj_list, 10, &find_count); if (rc != CKR_OK) { testcase_fail("C_FindObjects() rc = %s", p11_get_ckr(rc)); goto destroy; } got_it = 0; /* Make sure we got the right ones */ for (i = 0; i < find_count; i++) { if (obj_list[i] == h_clock) { got_it++; } } } while (got_it == 0 && find_count != 0); rc = funcs->C_FindObjectsFinal(h_session); if (rc != CKR_OK) { testcase_fail("C_FindObjectsFinal() rc = %s", p11_get_ckr(rc)); } if (got_it != 1) { testcase_fail("could not find the corect object handle"); rc = -1; goto destroy; } testcase_pass("Looks okay..."); destroy: /* Destroy the created objects, don't clobber the rc */ loc_rc = funcs->C_DestroyObject(h_session, h_clock); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc)); destroy_2: loc_rc = funcs->C_DestroyObject(h_session, h_obj2); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc)); destroy_1: loc_rc = funcs->C_DestroyObject(h_session, h_obj1); if (loc_rc != CKR_OK) testcase_error("C_DestroyObject() rc = %s", p11_get_ckr(loc_rc)); loc_rc = funcs->C_Logout(h_session); if (loc_rc != CKR_OK) testcase_error("C_Logout() rc = %s", p11_get_ckr(loc_rc)); session_close: /* Close the session */ if ((loc_rc = funcs->C_CloseSession(h_session)) != CKR_OK) testcase_error("C_CloseSession() rc = %s", p11_get_ckr(loc_rc)); return rc; } CK_RV obj_mgmt_functions() { int rc, errors = 0; rc = do_CreateSessionObject(); if (rc) errors++; rc = do_CopyObject(); if (rc) errors++; rc = do_SetAttributeValues(); if (rc) errors++; rc = do_FindObjects(); if (rc) errors++; rc = do_HWFeatureSearch(); if (rc) errors++; rc = do_CreateTokenObjects(); if (rc) errors++; return errors++; } int main(int argc, char **argv) { CK_C_INITIALIZE_ARGS cinit_args; int rc; CK_RV rv; rc = do_ParseArgs(argc, argv); if (rc != 1) return rc; printf("Using slot #%lu...\n\n", SLOT_ID); printf("With option: no_init: %d, no_stop: %d, skip_token_obj: %d\n", no_init, no_stop, skip_token_obj); rc = do_GetFunctionList(); if (!rc) { testcase_error_f("(setup)", "do_GetFunctionList() rc = %s", p11_get_ckr(rc)); return rc; } memset(&cinit_args, 0x0, sizeof(cinit_args)); cinit_args.flags = CKF_OS_LOCKING_OK; // SAB Add calls to ALL functions before the C_Initialize gets hit 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; } rv = obj_mgmt_functions(); /* make sure we return non-zero if rv is non-zero */ return ((rv == 0) || (rv % 256) ? (int)rv : -1); }