summaryrefslogtreecommitdiff
path: root/src/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.c')
-rw-r--r--src/key.c497
1 files changed, 497 insertions, 0 deletions
diff --git a/src/key.c b/src/key.c
index 495cff4..e37cdfe 100644
--- a/src/key.c
+++ b/src/key.c
@@ -1,6 +1,503 @@
#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");
+
+ 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");
+
+ 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)
+ 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");
+ }
+
+ 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)
+ 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);
+ }
+ }
+ 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);
+ }
+ }
+ free(objects);
+ }
+
+ p11t_session_close(session);
+ }
+}
+
+
+/* ----------------------------------------------------------------------------------
+ * METHODS
+ */
+
CK_OBJECT_HANDLE
find_related_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_OBJECT_CLASS klass)
{