From cdaffa87e8578503bc2f86fe1c0a3e000233666d Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 24 Dec 2008 02:02:42 +0000 Subject: Add DSA key support to tests. --- src/Makefile.am | 1 + src/dsa.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/key.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/p11-tests.c | 1 + src/p11-tests.h | 8 +++ 5 files changed, 384 insertions(+), 6 deletions(-) create mode 100644 src/dsa.c diff --git a/src/Makefile.am b/src/Makefile.am index 33abf3f..82a7d26 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ p11_tests_SOURCES = \ certificate.c \ check.c \ config.c \ + dsa.c \ key.c \ module.c \ msg.c \ diff --git a/src/dsa.c b/src/dsa.c new file mode 100644 index 0000000..40e56bb --- /dev/null +++ b/src/dsa.c @@ -0,0 +1,196 @@ + +#include "p11-tests.h" + +#include +#include +#include + +#include + +static int +test_dsa_sign_verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_OBJECT_HANDLE privkey, DSA* dsa) +{ + CK_BYTE hash[20]; + CK_BYTE sig[P11T_BLOCK]; + CK_BYTE encsig[P11T_BLOCK]; + unsigned char *ptr; + CK_MECHANISM mech; + CK_ULONG n_hash, n_sig; + DSA_SIG *dsa_sig; + CK_RV rv; + int res, n_encsig; + + /* Hash the data for DSA */ + SHA1(p11t_test_data, p11t_test_data_size, hash); + n_hash = 20; + + mech.mechanism = CKM_DSA; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + P11T_SECTION("C_SignInit"); + + rv = (p11t_module_funcs->C_SignInit)(session, &mech, privkey); + P11T_CHECK_RV("CKM_DSA", rv, CKR_OK); + + P11T_SECTION("C_Sign"); + + n_sig = sizeof(sig); + rv = (p11t_module_funcs->C_Sign)(session, hash, n_hash, sig, &n_sig); + + /* Requires authentication */ + if (rv == CKR_USER_NOT_LOGGED_IN) { + rv = p11t_key_login_context_specific (session, privkey); + P11T_CHECK_RV("Always authenticate", rv, CKR_OK); + rv = (p11t_module_funcs->C_Sign)(session, hash, n_hash, sig, &n_sig); + } + P11T_CHECK_RV("CKM_DSA", rv, CKR_OK); + if(n_sig != 40) + P11T_CHECK_FAIL("Length of DSA signature"); + + + /* Verify the DSA signature via openssl */ + dsa_sig = DSA_SIG_new(); + assert (dsa_sig); + dsa_sig->r = BN_bin2bn(sig, 20, NULL); + dsa_sig->s = BN_bin2bn(sig + 20, 20, NULL); + ptr = encsig; + n_encsig = i2d_DSA_SIG(dsa_sig, &ptr); + DSA_SIG_free(dsa_sig); + res = DSA_verify(0, hash, n_hash, encsig, n_encsig, dsa); + if(res != 1) + P11T_CHECK_FAIL_MSG("Check valid DSA signature", p11t_msg_openssl()); + + + P11T_SECTION("C_VerifyInit"); + + rv = (p11t_module_funcs->C_VerifyInit)(session, &mech, key); + P11T_CHECK_RV("CKM_DSA", rv, CKR_OK); + + P11T_SECTION("C_Verify"); + + rv = (p11t_module_funcs->C_Verify)(session, hash, n_hash, sig, n_sig); + P11T_CHECK_RV("CKM_DSA", rv, CKR_OK); + + return CONTINUE; +} + +static int +test_dsa_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type) +{ + CK_OBJECT_HANDLE privkey; + CK_ATTRIBUTE attrs[1]; + CK_BBOOL can_verify = 0; + DSA *dsa; + + attrs[0].type = CKA_VERIFY; + attrs[0].ulValueLen = sizeof(CK_BBOOL); + attrs[0].pValue = &can_verify; + + if(!p11t_object_get (session, key, attrs, 1)) + return CONTINUE; + + dsa = p11t_key_export_public_dsa (session, key); + if(!dsa) + return CONTINUE; + + privkey = p11t_key_get_private (session, key); + if (privkey == CK_INVALID) + return CONTINUE; + + if(can_verify) + test_dsa_sign_verify(session, key, privkey, dsa); + + DSA_free(dsa); + + return CONTINUE; +} + +static int +test_dsa_private_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type) +{ + CK_OBJECT_HANDLE pubkey; + CK_ATTRIBUTE attrs[2]; + CK_BBOOL can_sign = 0; + DSA *dsa; + + attrs[0].type = CKA_SIGN; + attrs[0].ulValueLen = sizeof(CK_BBOOL); + attrs[0].pValue = &can_sign; + + if(!p11t_object_get(session, key, attrs, 1)) + return CONTINUE; + + pubkey = p11t_key_get_public(session, key); + if (pubkey == CK_INVALID) + return CONTINUE; + + dsa = p11t_key_export_public_dsa(session, pubkey); + if(!dsa) + return CONTINUE; + + if(can_sign) + test_dsa_sign_verify(session, pubkey, key, dsa); + + DSA_free(dsa); + + return CONTINUE; +} + +static void +test_dsa (CK_SLOT_ID slot, CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info) +{ + CK_SESSION_HANDLE session; + CK_ATTRIBUTE attrs[2]; + CK_ATTRIBUTE attr; + CK_OBJECT_CLASS klass; + CK_KEY_TYPE key_type = CKK_DSA; + CK_BBOOL token = CK_TRUE; + CK_OBJECT_HANDLE_PTR keys; + CK_ULONG i, n_keys; + + /* Find all keys that match this mechanism */ + attrs[0].type = CKA_TOKEN; + attrs[0].ulValueLen = sizeof(token); + attrs[0].pValue = &token; + attrs[1].type = CKA_KEY_TYPE; + attrs[1].ulValueLen = sizeof(key_type); + attrs[1].pValue = &key_type; + + session = p11t_session_open(slot, 0); + if(session == CK_INVALID) + return; + + if(!p11t_session_login(session)) + return; + + keys = p11t_object_find(session, attrs, 2, &n_keys); + if(!keys) + return; + + for(i = 0; i < n_keys; ++i) + { + attr.type = CKA_CLASS; + attr.ulValueLen = sizeof(klass); + attr.pValue = &klass; + + if(p11t_object_get(session, keys[i], &attr, 1)) + { + if(klass == CKO_PRIVATE_KEY) + test_dsa_private_key(session, keys[i], mech); + else if(klass == CKO_PUBLIC_KEY) + test_dsa_public_key(session, keys[i], mech); + } + } + + free(keys); +} + +void +p11t_dsa_tests(void) +{ + p11t_slot_for_each_mech(CKM_DSA, test_dsa); +} diff --git a/src/key.c b/src/key.c index 0fa4c4b..977877a 100644 --- a/src/key.c +++ b/src/key.c @@ -145,6 +145,66 @@ test_rsa_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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; } @@ -191,7 +251,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -204,7 +264,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -216,7 +276,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -228,7 +288,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -240,7 +300,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -252,7 +312,7 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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) + 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); @@ -272,6 +332,69 @@ test_rsa_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) 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; } @@ -471,6 +594,8 @@ p11t_key_tests(void) 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); } } free(objects); @@ -488,6 +613,8 @@ p11t_key_tests(void) 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); @@ -575,6 +702,51 @@ p11t_key_export_public_rsa(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) 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) { diff --git a/src/p11-tests.c b/src/p11-tests.c index 0374dc4..b3e72d1 100644 --- a/src/p11-tests.c +++ b/src/p11-tests.c @@ -66,6 +66,7 @@ main(int argc, char* argv[]) p11t_key_tests(); p11t_certificate_tests(); p11t_rsa_tests(); + p11t_dsa_tests(); /* Remaining module tests */ p11t_module_finalize(); diff --git a/src/p11-tests.h b/src/p11-tests.h index 2bf4c53..d53a58a 100644 --- a/src/p11-tests.h +++ b/src/p11-tests.h @@ -15,6 +15,7 @@ #include #include +#include #define CK_INVALID ((CK_ULONG)-1) @@ -110,6 +111,12 @@ int _p11t_check_date(const char *what, CK_DATE* value); void p11t_config_parse(const char* filename); void p11t_config_cleanup(void); +/* ------------------------------------------------------------------- + * dsa.c + */ + +void p11t_dsa_tests(void); + /* ------------------------------------------------------------------- * key.c */ @@ -119,6 +126,7 @@ CK_OBJECT_HANDLE p11t_key_get_public(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE CK_OBJECT_HANDLE p11t_key_get_private(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); RSA* p11t_key_export_public_rsa(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); +DSA* p11t_key_export_public_dsa(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); CK_RV p11t_key_login_context_specific (CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); -- cgit v1.2.3