#include "p11-tests.h" /* ---------------------------------------------------------------------------------- * TESTS */ static int test_key_attributes(CK_SLOT_ID slot, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, CK_KEY_TYPE* key_type) { CK_BYTE buffer[4096]; CK_ATTRIBUTE attr; CK_MECHANISM_TYPE mech_type; CK_MECHANISM_TYPE_PTR mechanisms; CK_ULONG n_mechanisms, i; CK_BBOOL bval, local; CK_DATE date; CK_RV rv; P11T_SECTION("Key Object"); attr.type = CKA_KEY_TYPE; attr.ulValueLen = sizeof(*key_type); attr.pValue = key_type; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_KEY_TYPE", rv, CKR_OK); attr.type = CKA_ID; attr.ulValueLen = sizeof(buffer); attr.pValue = buffer; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_ID", rv, CKR_OK); attr.type = CKA_DERIVE; attr.ulValueLen = sizeof(bval); attr.pValue = &bval; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_DERIVE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_DERIVE", bval); if(p11t_test_unexpected) { attr.type = CKA_START_DATE; attr.ulValueLen = sizeof(date); attr.pValue = &date; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_START_DATE", rv, CKR_OK); if(attr.ulValueLen > 0) P11T_CHECK_DATE("CKA_START_DATE", &date); attr.type = CKA_END_DATE; attr.ulValueLen = sizeof(date); attr.pValue = &date; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_END_DATE", rv, CKR_OK); if(attr.ulValueLen > 0) P11T_CHECK_DATE("CKA_END_DATE", &date); attr.type = CKA_LOCAL; attr.ulValueLen = sizeof(local); attr.pValue = &local; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_LOCAL", rv, CKR_OK); P11T_CHECK_BOOL("CKA_LOCAL", local); attr.type = CKA_KEY_GEN_MECHANISM; attr.ulValueLen = sizeof(mech_type); attr.pValue = &mech_type; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_KEY_GEN_MECHANISM", rv, CKR_OK); /* Key was generated with this */ if(mech_type != CK_UNAVAILABLE_INFORMATION) { if(!local) P11T_CHECK_FAIL_MSG("CKA_KEY_GEN_MECHANISM", "Non locally generated key has key gen mechanism"); if(!p11t_slot_get_mech_info(slot, mech_type)) P11T_CHECK_FAIL_MSG("CKA_KEY_GEN_MECHANISM", "Mechanism not present on slot"); } attr.type = CKA_ALLOWED_MECHANISMS; attr.ulValueLen = sizeof(buffer); attr.pValue = buffer; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_ALLOWED_MECHANISMS", rv, CKR_OK); if(attr.ulValueLen % sizeof(CK_MECHANISM_TYPE) != 0) P11T_CHECK_FAIL_MSG("CKA_ALLOWED_MECHANISMS", "Invalid size memory returned"); mechanisms = (CK_MECHANISM_TYPE_PTR)buffer; n_mechanisms = attr.ulValueLen / sizeof(CK_MECHANISM_TYPE); for(i = 0; i < n_mechanisms; ++i) { if(!p11t_slot_get_mech_info(slot, mechanisms[i])) P11T_CHECK_FAIL_MSG("CKA_ALLOWED_MECHANISMS", "Mechanism not present in slot"); } } return CONTINUE; } static int test_rsa_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_ATTRIBUTE attr; CK_BYTE modulus[16384]; CK_ULONG n_modulus; CK_BYTE exponent[1024]; CK_ULONG n_exponent; CK_ULONG bits; CK_RV rv; RSA* rsa; P11T_SECTION("CKK_RSA Public"); /* * These attribute buffer codes have already been tested here and there, but * do it again since sometimes the big num code is different from general attrs. */ if(p11t_test_unexpected) { /* Too small */ attr.type = CKA_MODULUS; attr.pValue = modulus; attr.ulValueLen = 4; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_MODULUS", rv, CKR_BUFFER_TOO_SMALL); /* No buffer */ attr.type = CKA_MODULUS; attr.pValue = NULL; rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_MODULUS", rv, CKR_OK); } attr.type = CKA_MODULUS; attr.pValue = modulus; attr.ulValueLen = sizeof(modulus); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_MODULUS", rv, CKR_OK); n_modulus = attr.ulValueLen; attr.type = CKA_PUBLIC_EXPONENT; attr.pValue = exponent; attr.ulValueLen = sizeof(exponent); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_PUBLIC_EXPONENT", rv, CKR_OK); n_exponent = attr.ulValueLen; attr.type = CKA_MODULUS_BITS; attr.pValue = &bits; attr.ulValueLen = sizeof(bits); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_MODULUS_BITS", rv, CKR_OK); rsa = RSA_new(); assert(rsa); rsa->n = BN_bin2bn(modulus, n_modulus, NULL); if(!rsa->n) P11T_CHECK_FAIL_MSG("CKA_MODULUS", "Couldn't parse"); rsa->e = BN_bin2bn(exponent, n_exponent, NULL); if(!rsa->e) P11T_CHECK_FAIL_MSG("CKA_PUBLIC_EXPONENT", "Couldn't parse"); if(RSA_size(rsa) != bits / 8) P11T_CHECK_FAIL_MSG("CKA_MODULUS_BITS", "Does not match bits in actual modulus"); RSA_free(rsa); return CONTINUE; } static int test_dsa_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_ATTRIBUTE attr; CK_BYTE buffer[16384]; CK_RV rv; DSA* dsa; P11T_SECTION("CKK_DSA Public"); dsa = DSA_new(); assert(dsa); attr.type = CKA_PRIME; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_PRIME", rv, CKR_OK); dsa->p = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->p == NULL) P11T_CHECK_FAIL_MSG("CKA_PRIME", p11t_msg_openssl()); if(attr.ulValueLen % 8 != 0) P11T_CHECK_FAIL_MSG("CKA_PRIME", "Must be in steps of 64 bits"); attr.type = CKA_SUBPRIME; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SUBPRIME", rv, CKR_OK); dsa->q = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->q == NULL) P11T_CHECK_FAIL_MSG("CKA_SUBPRIME", p11t_msg_openssl()); if(attr.ulValueLen != 20) P11T_CHECK_FAIL_MSG("CKA_SUBPRIME", "Must be 160 bits"); attr.type = CKA_BASE; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_BASE", rv, CKR_OK); dsa->g = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->g == NULL) P11T_CHECK_FAIL_MSG("CKA_BASE", p11t_msg_openssl()); attr.type = CKA_VALUE; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_VALUE", rv, CKR_OK); dsa->pub_key = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->pub_key == NULL) P11T_CHECK_FAIL_MSG("CKA_VALUE", p11t_msg_openssl()); DSA_free(dsa); return CONTINUE; } static int test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_ATTRIBUTE attr; CK_BYTE buffer[32768]; CK_RV rv; RSA* rsa; P11T_SECTION("CKK_RSA Private"); rsa = RSA_new(); assert(rsa); attr.type = CKA_MODULUS; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_MODULUS", rv, CKR_OK); rsa->n = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->n == NULL) P11T_CHECK_FAIL_MSG("CKA_MODULUS", p11t_msg_openssl()); attr.type = CKA_PRIVATE_EXPONENT; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv == CKR_ATTRIBUTE_SENSITIVE) { RSA_free(rsa); return CONTINUE; } P11T_CHECK_RV("CKA_PRIVATE_EXPONENT", rv, CKR_OK); rsa->d = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->d == NULL) P11T_CHECK_FAIL_MSG("CKA_PRIVATE_EXPONENT", p11t_msg_openssl()); if(p11t_test_unexpected) { attr.type = CKA_PUBLIC_EXPONENT; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_PUBLIC_EXPONENT", rv, CKR_OK); rsa->e = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->e == NULL) P11T_CHECK_FAIL_MSG("CKA_PUBLIC_EXPONENT", p11t_msg_openssl()); } attr.type = CKA_PRIME_1; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_PRIME_1", rv, CKR_OK); rsa->p = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->p == NULL) P11T_CHECK_FAIL_MSG("CKA_PRIME_1", p11t_msg_openssl()); } attr.type = CKA_PRIME_2; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_PRIME_2", rv, CKR_OK); rsa->q = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->q == NULL) P11T_CHECK_FAIL_MSG("CKA_PRIME_2", p11t_msg_openssl()); } attr.type = CKA_EXPONENT_1; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_EXPONENT_1", rv, CKR_OK); rsa->dmp1 = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->dmp1 == NULL) P11T_CHECK_FAIL_MSG("CKA_EXPONENT_1", p11t_msg_openssl()); } attr.type = CKA_EXPONENT_2; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_EXPONENT_2", rv, CKR_OK); rsa->dmq1 = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->dmq1 == NULL) P11T_CHECK_FAIL_MSG("CKA_EXPONENT_2", p11t_msg_openssl()); } attr.type = CKA_COEFFICIENT; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_COEFFICIENT", rv, CKR_OK); rsa->iqmp = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(rsa->iqmp == NULL) P11T_CHECK_FAIL_MSG("CKA_COEFFICIENT", p11t_msg_openssl()); } } /* Can we validate the key? */ assert(rsa->n && rsa->d); if(rsa->e && rsa->p && rsa->q) { int res = RSA_check_key(rsa); if(res < 0) P11T_CHECK_FAIL_MSG("Check RSA private key", p11t_msg_openssl()); else if(res == 0) P11T_CHECK_FAIL_MSG("Check RSA private key", "RSA key is not valid"); } RSA_free(rsa); return CONTINUE; } static int test_dsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_ATTRIBUTE attr; CK_BYTE buffer[16384]; CK_RV rv; DSA* dsa; P11T_SECTION("CKK_DSA Private"); dsa = DSA_new(); assert(dsa); attr.type = CKA_PRIME; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_PRIME", rv, CKR_OK); dsa->p = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->p == NULL) P11T_CHECK_FAIL_MSG("CKA_PRIME", p11t_msg_openssl()); if(attr.ulValueLen % 8 != 0) P11T_CHECK_FAIL_MSG("CKA_PRIME", "Must be in steps of 64 bits"); attr.type = CKA_SUBPRIME; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SUBPRIME", rv, CKR_OK); dsa->q = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->q == NULL) P11T_CHECK_FAIL_MSG("CKA_SUBPRIME", p11t_msg_openssl()); if(attr.ulValueLen != 20) P11T_CHECK_FAIL_MSG("CKA_SUBPRIME", "Must be 160 bits"); attr.type = CKA_BASE; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_BASE", rv, CKR_OK); dsa->g = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->g == NULL) P11T_CHECK_FAIL_MSG("CKA_BASE", p11t_msg_openssl()); attr.type = CKA_VALUE; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); if(rv != CKR_ATTRIBUTE_SENSITIVE && rv != CKR_ATTRIBUTE_TYPE_INVALID) { P11T_CHECK_RV("CKA_VALUE", rv, CKR_OK); dsa->priv_key = BN_bin2bn(attr.pValue, attr.ulValueLen, NULL); if(dsa->priv_key == NULL) P11T_CHECK_FAIL_MSG("CKA_VALUE", p11t_msg_openssl()); } DSA_free(dsa); return CONTINUE; } static int test_rsa_public_create(CK_SESSION_HANDLE session, CK_BBOOL token, RSA *rsa, CK_OBJECT_HANDLE_PTR result) { CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[10]; CK_KEY_TYPE key_type = CKK_RSA; CK_ULONG rsa_bits = 1024; CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY; CK_RV rv; P11T_SECTION("C_CreateObject"); /* Fill in all the attributes */ attrs[0].type = CKA_TOKEN; attrs[0].pValue = &token; attrs[0].ulValueLen = sizeof (token); attrs[1].type = CKA_CLASS; attrs[1].ulValueLen = sizeof (klass); attrs[1].pValue = &klass; attrs[2].type = CKA_LABEL; attrs[2].pValue = "Test Public Key"; attrs[2].ulValueLen = 15; attrs[3].type = CKA_KEY_TYPE; attrs[3].pValue = &key_type; attrs[3].ulValueLen = sizeof (key_type); attrs[4].type = CKA_MODULUS_BITS; attrs[4].pValue = &rsa_bits; attrs[4].ulValueLen = sizeof (rsa_bits); if(p11t_test_unexpected) { rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 5, &object); P11T_CHECK_RV("RSA Public incomplete template", rv, CKR_TEMPLATE_INCOMPLETE); } attrs[5].type = CKA_MODULUS; attrs[5].ulValueLen = BN_num_bytes (rsa->n); attrs[5].pValue = alloca (attrs[5].ulValueLen); BN_bn2bin (rsa->n, (unsigned char*)attrs[5].pValue); attrs[6].type = CKA_PUBLIC_EXPONENT; attrs[6].ulValueLen = BN_num_bytes (rsa->e); attrs[6].pValue = alloca (attrs[6].ulValueLen); BN_bn2bin (rsa->e, (unsigned char*)attrs[6].pValue); rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 7, &object); if (rv == CKR_TEMPLATE_INCOMPLETE) return CONTINUE; P11T_CHECK_RV("RSA Public Key", rv, CKR_OK); test_rsa_public (session, object); *result = object; return CONTINUE; } static int test_rsa_private_create(CK_SESSION_HANDLE session, CK_BBOOL token, RSA *rsa, CK_OBJECT_HANDLE_PTR result) { CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[10]; CK_KEY_TYPE key_type = CKK_RSA; CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY; CK_RV rv; P11T_SECTION("C_CreateObject"); /* Fill in all the attributes */ attrs[0].type = CKA_TOKEN; attrs[0].pValue = &token; attrs[0].ulValueLen = sizeof (token); attrs[1].type = CKA_CLASS; attrs[1].ulValueLen = sizeof (klass); attrs[1].pValue = &klass; attrs[2].type = CKA_LABEL; attrs[2].pValue = "Test Private Key"; attrs[2].ulValueLen = 15; attrs[3].type = CKA_KEY_TYPE; attrs[3].pValue = &key_type; attrs[3].ulValueLen = sizeof (key_type); attrs[4].type = CKA_MODULUS; attrs[4].ulValueLen = BN_num_bytes (rsa->n); attrs[4].pValue = alloca (attrs[4].ulValueLen); BN_bn2bin (rsa->n, (unsigned char*)attrs[4].pValue); attrs[5].type = CKA_PRIVATE_EXPONENT; attrs[5].ulValueLen = BN_num_bytes (rsa->d); attrs[5].pValue = alloca (attrs[5].ulValueLen); BN_bn2bin (rsa->d, (unsigned char*)attrs[5].pValue); attrs[6].type = CKA_PUBLIC_EXPONENT; attrs[6].ulValueLen = BN_num_bytes (rsa->e); attrs[6].pValue = alloca (attrs[6].ulValueLen); BN_bn2bin (rsa->e, (unsigned char*)attrs[6].pValue); attrs[7].type = CKA_PRIME_1; attrs[7].ulValueLen = BN_num_bytes (rsa->p); attrs[7].pValue = alloca (attrs[7].ulValueLen); BN_bn2bin (rsa->p, (unsigned char*)attrs[7].pValue); attrs[8].type = CKA_PRIME_2; attrs[8].ulValueLen = BN_num_bytes (rsa->q); attrs[8].pValue = alloca (attrs[8].ulValueLen); BN_bn2bin (rsa->q, (unsigned char*)attrs[8].pValue); rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 9, &object); if (rv == CKR_TEMPLATE_INCOMPLETE) return STOP; P11T_CHECK_RV("RSA Private Key", rv, CKR_OK); test_rsa_private (session, object); *result = object; return CONTINUE; } static int test_rsa_create(CK_SESSION_HANDLE session, CK_BBOOL token) { CK_OBJECT_HANDLE pub, prv; CK_RV rv; RSA *rsa; rsa = RSA_generate_key (1024, 17, NULL, NULL); assert (rsa); pub = prv = 0; test_rsa_public_create (session, token, rsa, &pub); test_rsa_private_create (session, token, rsa, &prv); if (pub != 0) p11t_rsa_test_public_key (session, pub); if (prv != 0) p11t_rsa_test_private_key (session, prv); P11T_SECTION("C_DestroyObject"); rv = (p11t_module_funcs->C_DestroyObject)(session, pub); P11T_CHECK_RV("RSA Public Key", rv, CKR_OK); rv = (p11t_module_funcs->C_DestroyObject)(session, pub); P11T_CHECK_RV("Deleted object", rv, CKR_OBJECT_HANDLE_INVALID); RSA_free (rsa); return CONTINUE; } static int test_dsa_public_create(CK_SESSION_HANDLE session, CK_BBOOL token, DSA *dsa, CK_OBJECT_HANDLE_PTR result) { CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[10]; CK_KEY_TYPE key_type = CKK_DSA; CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY; CK_RV rv; P11T_SECTION("C_CreateObject"); /* Fill in all the attributes */ attrs[0].type = CKA_TOKEN; attrs[0].pValue = &token; attrs[0].ulValueLen = sizeof (token); attrs[1].type = CKA_CLASS; attrs[1].ulValueLen = sizeof (klass); attrs[1].pValue = &klass; attrs[2].type = CKA_LABEL; attrs[2].pValue = "Test DSA Public Key"; attrs[2].ulValueLen = 19; attrs[3].type = CKA_KEY_TYPE; attrs[3].pValue = &key_type; attrs[3].ulValueLen = sizeof (key_type); attrs[4].type = CKA_PRIME; attrs[4].ulValueLen = BN_num_bytes (dsa->p); attrs[4].pValue = alloca (attrs[4].ulValueLen); BN_bn2bin (dsa->p, (unsigned char*)attrs[4].pValue); attrs[5].type = CKA_SUBPRIME; attrs[5].ulValueLen = BN_num_bytes (dsa->q); attrs[5].pValue = alloca (attrs[5].ulValueLen); BN_bn2bin (dsa->q, (unsigned char*)attrs[5].pValue); attrs[6].type = CKA_BASE; attrs[6].ulValueLen = BN_num_bytes (dsa->g); attrs[6].pValue = alloca (attrs[6].ulValueLen); BN_bn2bin (dsa->g, (unsigned char*)attrs[6].pValue); attrs[7].type = CKA_VALUE; attrs[7].ulValueLen = BN_num_bytes (dsa->pub_key); attrs[7].pValue = alloca (attrs[7].ulValueLen); BN_bn2bin (dsa->pub_key, (unsigned char*)attrs[7].pValue); rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 8, &object); if (rv == CKR_TEMPLATE_INCOMPLETE) return CONTINUE; P11T_CHECK_RV("DSA Public Key", rv, CKR_OK); test_dsa_public (session, object); *result = object; return CONTINUE; } static int test_dsa_private_create(CK_SESSION_HANDLE session, CK_BBOOL token, DSA *dsa, CK_OBJECT_HANDLE_PTR result) { CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[10]; CK_KEY_TYPE key_type = CKK_DSA; CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY; CK_RV rv; P11T_SECTION("C_CreateObject"); /* Fill in all the attributes */ attrs[0].type = CKA_TOKEN; attrs[0].pValue = &token; attrs[0].ulValueLen = sizeof (token); attrs[1].type = CKA_CLASS; attrs[1].ulValueLen = sizeof (klass); attrs[1].pValue = &klass; attrs[2].type = CKA_LABEL; attrs[2].pValue = "Test DSA Private Key"; attrs[2].ulValueLen = 20; attrs[3].type = CKA_KEY_TYPE; attrs[3].pValue = &key_type; attrs[3].ulValueLen = sizeof (key_type); attrs[4].type = CKA_PRIME; attrs[4].ulValueLen = BN_num_bytes (dsa->p); attrs[4].pValue = alloca (attrs[4].ulValueLen); BN_bn2bin (dsa->p, (unsigned char*)attrs[4].pValue); attrs[5].type = CKA_SUBPRIME; attrs[5].ulValueLen = BN_num_bytes (dsa->q); attrs[5].pValue = alloca (attrs[5].ulValueLen); BN_bn2bin (dsa->q, (unsigned char*)attrs[5].pValue); attrs[6].type = CKA_BASE; attrs[6].ulValueLen = BN_num_bytes (dsa->g); attrs[6].pValue = alloca (attrs[6].ulValueLen); BN_bn2bin (dsa->g, (unsigned char*)attrs[6].pValue); attrs[7].type = CKA_VALUE; attrs[7].ulValueLen = BN_num_bytes (dsa->priv_key); attrs[7].pValue = alloca (attrs[7].ulValueLen); BN_bn2bin (dsa->priv_key, (unsigned char*)attrs[7].pValue); rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 8, &object); if (rv == CKR_TEMPLATE_INCOMPLETE) return CONTINUE; P11T_CHECK_RV("DSA Private Key", rv, CKR_OK); test_dsa_private (session, object); *result = object; return CONTINUE; } static int test_dsa_create(CK_SESSION_HANDLE session, CK_BBOOL token) { CK_OBJECT_HANDLE pub, prv; CK_RV rv; DSA *dsa; int ret; dsa = DSA_generate_parameters(1024, NULL, 0, NULL, NULL, NULL, NULL); assert (dsa); ret = DSA_generate_key (dsa); assert (ret == 1); pub = prv = 0; test_dsa_public_create (session, token, dsa, &pub); test_dsa_private_create (session, token, dsa, &prv); if (pub != 0) p11t_dsa_test_public_key (session, pub); if (prv != 0) p11t_dsa_test_private_key (session, prv); P11T_SECTION("C_DestroyObject"); rv = (p11t_module_funcs->C_DestroyObject)(session, pub); P11T_CHECK_RV("DSA Public Key", rv, CKR_OK); DSA_free (dsa); return CONTINUE; } static int test_create_unexpected(CK_SESSION_HANDLE session) { CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[1]; CK_BBOOL token = CK_FALSE; CK_RV rv; if(!p11t_test_unexpected) return CONTINUE; P11T_SECTION("C_CreateObject"); /* Fill in all the attributes */ attrs[0].type = CKA_TOKEN; attrs[0].pValue = &token; attrs[0].ulValueLen = sizeof (token); rv = (p11t_module_funcs->C_CreateObject)((CK_SESSION_HANDLE)-83, attrs, 1, &object); P11T_CHECK_RV("Invalid session", rv, CKR_SESSION_HANDLE_INVALID); rv = (p11t_module_funcs->C_CreateObject)(session, NULL, 1, &object); P11T_CHECK_RV("Invalid session", rv, CKR_ARGUMENTS_BAD); rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 1, NULL); P11T_CHECK_RV("Invalid session", rv, CKR_ARGUMENTS_BAD); /* No class in the template */ rv = (p11t_module_funcs->C_CreateObject)(session, attrs, 1, &object); P11T_CHECK_RV("Invalid session", rv, CKR_TEMPLATE_INCOMPLETE); return CONTINUE; } static int test_public_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_BYTE buffer[4096]; CK_ATTRIBUTE attr; CK_BBOOL bval, wrap; const char *msg; CK_RV rv; P11T_SECTION("CKO_PUBLIC_KEY"); attr.type = CKA_SUBJECT; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SUBJECT", rv, CKR_OK); if(attr.ulValueLen) { msg = p11t_certificate_validate_dn(attr.pValue, attr.ulValueLen); if(msg != NULL) P11T_CHECK_FAIL_MSG("CKA_SUBJECT", msg); } attr.type = CKA_ENCRYPT; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_ENCRYPT", rv, CKR_OK); P11T_CHECK_BOOL("CKA_ENCRYPT", bval); attr.type = CKA_VERIFY; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_VERIFY", rv, CKR_OK); P11T_CHECK_BOOL("CKA_VERIFY", bval); attr.type = CKA_VERIFY_RECOVER; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_VERIFY_RECOVER", rv, CKR_OK); P11T_CHECK_BOOL("CKA_VERIFY_RECOVER", bval); attr.type = CKA_TRUSTED; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_TRUSTED", rv, CKR_OK); P11T_CHECK_BOOL("CKA_TRUSTED", bval); attr.type = CKA_WRAP; attr.pValue = &wrap; attr.ulValueLen = sizeof(wrap); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_WRAP", rv, CKR_OK); P11T_CHECK_BOOL("CKA_WRAP", wrap); return CONTINUE; } static int test_private_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) { CK_BYTE buffer[4096]; CK_ATTRIBUTE attr; CK_BBOOL bval; const char *msg; CK_RV rv; P11T_SECTION("CKO_PRIVATE_KEY"); attr.type = CKA_SUBJECT; attr.pValue = buffer; attr.ulValueLen = sizeof(buffer); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SUBJECT", rv, CKR_OK); if(attr.ulValueLen) { msg = p11t_certificate_validate_dn(attr.pValue, attr.ulValueLen); if(msg != NULL) P11T_CHECK_FAIL_MSG("CKA_SUBJECT", msg); } attr.type = CKA_SENSITIVE; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SENSITIVE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_SENSITIVE", bval); attr.type = CKA_DECRYPT; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_DECRYPT", rv, CKR_OK); P11T_CHECK_BOOL("CKA_DECRYPT", bval); attr.type = CKA_SIGN; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SIGN", rv, CKR_OK); P11T_CHECK_BOOL("CKA_SIGN", bval); attr.type = CKA_SIGN_RECOVER; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_SIGN_RECOVER", rv, CKR_OK); P11T_CHECK_BOOL("CKA_SIGN_RECOVER", bval); attr.type = CKA_UNWRAP; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_UNWRAP", rv, CKR_OK); P11T_CHECK_BOOL("CKA_UNWRAP", bval); attr.type = CKA_EXTRACTABLE; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_EXTRACTABLE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_EXTRACTABLE", bval); attr.type = CKA_ALWAYS_SENSITIVE; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_ALWAYS_SENSITIVE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_ALWAYS_SENSITIVE", bval); attr.type = CKA_NEVER_EXTRACTABLE; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_NEVER_EXTRACTABLE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_NEVER_EXTRACTABLE", bval); if(p11t_test_unexpected) { attr.type = CKA_WRAP_WITH_TRUSTED; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_WRAP_WITH_TRUSTED", rv, CKR_OK); P11T_CHECK_BOOL("CKA_WRAP_WITH_TRUSTED", bval); attr.type = CKA_ALWAYS_AUTHENTICATE; attr.pValue = &bval; attr.ulValueLen = sizeof(bval); rv = (p11t_module_funcs->C_GetAttributeValue)(session, object, &attr, 1); P11T_CHECK_RV("CKA_ALWAYS_AUTHENTICATE", rv, CKR_OK); P11T_CHECK_BOOL("CKA_ALWAYS_AUTHENTICATE", bval); } return CONTINUE; } void p11t_key_tests(void) { CK_OBJECT_CLASS klass; CK_OBJECT_HANDLE_PTR objects; CK_SESSION_HANDLE session; CK_OBJECT_HANDLE object; CK_ATTRIBUTE attrs[1]; CK_ULONG j, i, n_objects; CK_SLOT_ID slot; CK_KEY_TYPE key_type; attrs[0].type = CKA_CLASS; attrs[0].ulValueLen = sizeof(klass); attrs[0].pValue = &klass; for(j = 0; j < p11t_slot_count; ++j) { slot = p11t_slot_get_id(j); session = p11t_session_open(slot, 0); if(session == CK_INVALID) continue; klass = CKO_PUBLIC_KEY; objects = p11t_object_find(session, attrs, 1, &n_objects); for(i = 0; objects && i < n_objects; ++i) { object = objects[i]; if(test_key_attributes(slot, session, object, &key_type)) { test_public_attributes(session, object); if(key_type == CKK_RSA) test_rsa_public(session, object); else if(key_type == CKK_DSA) test_dsa_public(session, object); } } if(p11t_test_write_session) test_create_unexpected(session); free(objects); if(p11t_session_login(session)) { klass = CKO_PRIVATE_KEY; objects = p11t_object_find(session, attrs, 1, &n_objects); for(i = 0; objects && i < n_objects; ++i) { object = objects[i]; if(test_key_attributes(slot, session, object, &key_type)) { test_private_attributes(session, object); if(key_type == CKK_RSA) test_rsa_private(session, object); else if(key_type == CKK_DSA) test_dsa_private(session, object); } } free(objects); if (p11t_test_write_session) { test_rsa_create (session, CK_FALSE); test_dsa_create (session, CK_FALSE); } } p11t_session_close(session); } } /* ---------------------------------------------------------------------------------- * METHODS */ CK_OBJECT_HANDLE find_related_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_OBJECT_CLASS klass) { CK_BYTE id[4096]; CK_ATTRIBUTE attrs[2]; attrs[0].type = CKA_ID; attrs[0].pValue = id; attrs[0].ulValueLen = sizeof(id); if(!p11t_object_get(session, key, attrs, 1)) return CK_INVALID; attrs[1].type = CKA_CLASS; attrs[1].ulValueLen = sizeof(klass); attrs[1].pValue = &klass; return p11t_object_find_one(session, attrs, 2); } CK_OBJECT_HANDLE p11t_key_get_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { return find_related_object(session, key, CKO_PUBLIC_KEY); } CK_OBJECT_HANDLE p11t_key_get_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { return find_related_object(session, key, CKO_PRIVATE_KEY); } RSA* p11t_key_export_public_rsa(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { CK_ATTRIBUTE attrs[3]; CK_BYTE modulus[4096]; CK_BYTE public_exponent[4096]; CK_ULONG modulus_bits; RSA *rsa; attrs[0].type = CKA_MODULUS; attrs[0].ulValueLen = sizeof(modulus); attrs[0].pValue = modulus; attrs[1].type = CKA_MODULUS_BITS; attrs[1].ulValueLen = sizeof(modulus_bits); attrs[1].pValue = &modulus_bits; attrs[2].type = CKA_PUBLIC_EXPONENT; attrs[2].ulValueLen = sizeof(public_exponent); attrs[2].pValue = public_exponent; if(!p11t_object_get(session, key, attrs, 3)) return NULL; if(attrs[0].ulValueLen == CK_INVALID || attrs[2].ulValueLen == CK_INVALID) return NULL; rsa = RSA_new(); rsa->n = BN_bin2bn(modulus, attrs[0].ulValueLen, NULL); rsa->e = BN_bin2bn(public_exponent, attrs[2].ulValueLen, NULL); assert(rsa && rsa->n && rsa->e); if(attrs[1].ulValueLen != CK_INVALID) { assert(RSA_size(rsa) == modulus_bits / 8); } return rsa; } DSA* p11t_key_export_public_dsa(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { CK_ATTRIBUTE attrs[4]; CK_BYTE prime[4096]; CK_BYTE subprime[4096]; CK_BYTE base[4096]; CK_BYTE value[4096]; DSA *dsa; attrs[0].type = CKA_PRIME; attrs[0].ulValueLen = sizeof(prime); attrs[0].pValue = prime; attrs[1].type = CKA_SUBPRIME; attrs[1].ulValueLen = sizeof(subprime); attrs[1].pValue = subprime; attrs[2].type = CKA_BASE; attrs[2].ulValueLen = sizeof(base); attrs[2].pValue = base; attrs[3].type = CKA_VALUE; attrs[3].ulValueLen = sizeof(value); attrs[3].pValue = value; if(!p11t_object_get(session, key, attrs, 4)) return NULL; if(attrs[0].ulValueLen == CK_INVALID || attrs[1].ulValueLen == CK_INVALID || attrs[2].ulValueLen == CK_INVALID || attrs[3].ulValueLen == CK_INVALID) return NULL; dsa = DSA_new(); dsa->p = BN_bin2bn(prime, attrs[0].ulValueLen, NULL); dsa->q = BN_bin2bn(subprime, attrs[1].ulValueLen, NULL); dsa->g = BN_bin2bn(base, attrs[2].ulValueLen, NULL); dsa->pub_key = BN_bin2bn(value, attrs[3].ulValueLen, NULL); assert(dsa && dsa->p && dsa->q && dsa->g && dsa->pub_key); return dsa; } CK_RV p11t_key_login_context_specific (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) { CK_SESSION_INFO info; CK_ATTRIBUTE attr; CK_BBOOL always; CK_UTF8CHAR_PTR pin; CK_ULONG n_pin; CK_RV rv; assert(session != CK_INVALID); assert(p11t_module_funcs); if (key != CK_INVALID) { attr.type = CKA_ALWAYS_AUTHENTICATE; attr.ulValueLen = sizeof (always); attr.pValue = &always; if (!p11t_object_get (session, key, &attr, 1) || !always) { p11t_check_fail ("Key wants context specific login, but CKA_ALWAYS_AUTHENTICATE not set"); return CKR_ATTRIBUTE_VALUE_INVALID; } } rv = (p11t_module_funcs->C_GetSessionInfo)(session, &info); if (rv != CKR_OK) return rv; pin = p11t_session_get_pin (info.slotID, CKU_CONTEXT_SPECIFIC, &n_pin); return (p11t_module_funcs->C_Login)(session, CKU_CONTEXT_SPECIFIC, pin, n_pin); } CK_MECHANISM_TYPE_PTR p11t_key_get_mechanisms(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_ULONG_PTR n_mechanisms) { CK_ATTRIBUTE attr; attr.type = CKA_ALLOWED_MECHANISMS; attr.pValue = NULL; attr.ulValueLen = 0; if (!p11t_object_get(session, key, &attr, 1)) return NULL; attr.pValue = malloc(attr.ulValueLen); assert (attr.pValue); if (!p11t_object_get (session, key, &attr, 1)) { free (attr.pValue); return NULL; } *n_mechanisms = attr.ulValueLen / sizeof (CK_MECHANISM_TYPE); return attr.pValue; }