From 746579baf9176eb13dc19e98627e27e900c9859d Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 5 Dec 2008 22:48:19 +0000 Subject: Implement RSA sign tests. --- doc/pkcs11-coverage.txt | 5 + src/Makefile.am | 2 +- src/rsa-pkcs.c | 250 ---------------------------- src/rsa.c | 420 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 426 insertions(+), 251 deletions(-) delete mode 100644 src/rsa-pkcs.c create mode 100644 src/rsa.c diff --git a/doc/pkcs11-coverage.txt b/doc/pkcs11-coverage.txt index b96ee08..2885915 100644 --- a/doc/pkcs11-coverage.txt +++ b/doc/pkcs11-coverage.txt @@ -177,6 +177,11 @@ C_SetOperationState C_SetPIN - Not Implemented +C_Sign +- CKM_RSA_PKCS (SHA1) +- CKM_RSA_PKCS (MD5) +- CKM_RSA_PKCS (SHA1/MD5/SSL3) + C_WaitForSlotEvent - Not Implemented diff --git a/src/Makefile.am b/src/Makefile.am index 6e51a6f..5139896 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,7 +11,7 @@ p11_tests_SOURCES = \ msg.c \ object.c \ p11-tests.c \ - rsa-pkcs.c \ + rsa.c \ session.c \ slot.c \ test-data.c diff --git a/src/rsa-pkcs.c b/src/rsa-pkcs.c deleted file mode 100644 index e97a3b0..0000000 --- a/src/rsa-pkcs.c +++ /dev/null @@ -1,250 +0,0 @@ - -#include "config.h" - -#include "p11-tests.h" - -#include -#include -#include - -void -test_rsa_decrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, - CK_MECHANISM_TYPE mech_type, RSA* rsa) -{ - CK_BYTE encrypted[p11t_test_data_size]; - CK_BYTE decrypted[p11t_test_data_size]; - CK_MECHANISM mech; - const CK_BYTE* data; - CK_ULONG n_data, n_decrypted; - int size, n_encrypted; - CK_RV rv; - - /** C_Decrypt */ - - data = p11t_test_data; - n_data = p11t_test_data_size; - - size = RSA_size(rsa); - assert(size); - assert(size < sizeof(encrypted)); - assert(size < sizeof(decrypted)); - assert(size < n_data); - - switch(mech_type) - { - case CKM_RSA_PKCS: - /** - CKM_RSA_PKCS */ - n_data = size - 11; - n_encrypted = RSA_public_encrypt(n_data, data, encrypted, rsa, RSA_PKCS1_PADDING); - assert(n_encrypted == size); - break; - case CKM_RSA_X_509: - /** - CKM_RSA_X_509 */ - n_data = size; - n_encrypted = RSA_public_encrypt(n_data, data, encrypted, rsa, RSA_NO_PADDING); - assert(n_encrypted == size); - break; - default: - return; - }; - - mech.mechanism = mech_type; - mech.pParameter = NULL; - mech.ulParameterLen = 0; - - rv = (p11t_module_funcs->C_DecryptInit)(session, &mech, key); - p11t_check_returns("C_DecryptInit: rsa", rv, CKR_OK); - - n_decrypted = sizeof(decrypted); - rv = (p11t_module_funcs->C_Decrypt)(session, encrypted, n_encrypted, decrypted, &n_decrypted); - p11t_check_returns("C_Decrypt: rsa", rv, CKR_OK); - - if(n_decrypted != n_data) - p11t_check_fail("C_Decrypt: rsa decrypt failed, wrong length"); - if(memcmp(data, decrypted, n_data) != 0) - p11t_check_fail("C_Decrypt: rsa decrypt failed, bad data"); -} - -void -test_rsa_encrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, - CK_MECHANISM_TYPE mech_type, RSA* rsa) -{ - CK_BYTE encrypted[p11t_test_data_size]; - CK_BYTE check[p11t_test_data_size]; - CK_OBJECT_HANDLE privkey; - CK_MECHANISM mech; - const CK_BYTE* data; - CK_ULONG n_data, n_check, n_encrypted; - int size; - CK_RV rv; - - data = p11t_test_data; - n_data = p11t_test_data_size; - - /** C_Encrypt */ - - size = RSA_size(rsa); - assert(size); - assert(size < sizeof(encrypted)); - assert(size < sizeof(check)); - assert(size < n_data); - - switch(mech_type) - { - case CKM_RSA_PKCS: - /** - CKM_RSA_PKCS */ - n_data = size - 11; - break; - case CKM_RSA_X_509: - /** - CKM_RSA_X_509 */ - n_data = size; - break; - default: - return; - }; - - mech.mechanism = mech_type; - mech.pParameter = NULL; - mech.ulParameterLen = 0; - - /* Now ask PKCS#11 to decrypt it */ - rv = (p11t_module_funcs->C_EncryptInit)(session, &mech, key); - p11t_check_returns("C_EncryptInit: rsa", rv, CKR_OK); - - n_encrypted = sizeof(encrypted); - rv = (p11t_module_funcs->C_Encrypt)(session, (CK_BYTE*)data, n_data, encrypted, &n_encrypted); - p11t_check_returns("C_Encrypt: rsa", rv, CKR_OK); - - if(size != n_encrypted) - p11t_check_fail("C_Encrypt: rsa encrypt failed, wrong length"); - - /* We need to find a private key in order to validate */ - privkey = p11t_key_get_private(session, key); - if(privkey == CK_INVALID) - return; - - rv = (p11t_module_funcs->C_DecryptInit)(session, &mech, privkey); - p11t_check_returns("C_DecryptInit: rsa validate", rv, CKR_OK); - - n_check = sizeof(check); - rv = (p11t_module_funcs->C_Decrypt)(session, encrypted, n_encrypted, check, &n_check); - p11t_check_returns("C_Decrypt: rsa validate", rv, CKR_OK); - - if(n_check != n_data) - p11t_check_fail("C_Decrypt: rsa validate failed, wrong length"); - if(memcmp(data, check, n_data) != 0) - p11t_check_fail("C_Decrypt: rsa validate failed, bad data"); -} - -void -test_rsa_private_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, - CK_MECHANISM_TYPE mech_type) -{ - CK_ATTRIBUTE attrs[2]; - CK_BBOOL can_decrypt = 0; - CK_BBOOL can_sign = 0; - RSA *rsa; - - attrs[0].type = CKA_DECRYPT; - attrs[0].ulValueLen = sizeof(CK_BBOOL); - attrs[0].pValue = &can_decrypt; - attrs[1].type = CKA_SIGN; - attrs[1].ulValueLen = sizeof(CK_BBOOL); - attrs[1].pValue = &can_sign; - - if(!p11t_object_get(session, key, attrs, 2)) - return; - - rsa = p11t_key_export_public_rsa(session, key); - if(!rsa) - return; - - if(can_decrypt) - test_rsa_decrypt(session, key, mech_type, rsa); - - RSA_free(rsa); -} - -void -test_rsa_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, - CK_MECHANISM_TYPE mech_type) -{ - CK_ATTRIBUTE attrs[2]; - CK_BBOOL can_encrypt = 0; - CK_BBOOL can_verify = 0; - RSA *rsa; - - attrs[0].type = CKA_ENCRYPT; - attrs[0].ulValueLen = sizeof(CK_BBOOL); - attrs[0].pValue = &can_encrypt; - attrs[1].type = CKA_VERIFY; - attrs[1].ulValueLen = sizeof(CK_BBOOL); - attrs[1].pValue = &can_verify; - - if(!p11t_object_get(session, key, attrs, 2)) - return; - - rsa = p11t_key_export_public_rsa(session, key); - if(!rsa) - return; - - if(can_encrypt) - test_rsa_encrypt(session, key, mech_type, rsa); - - RSA_free(rsa); -} - -void -test_rsa_pkcs(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_RSA; - 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_rsa_private_key(session, keys[i], mech); - else if(klass == CKO_PUBLIC_KEY) - test_rsa_public_key(session, keys[i], mech); - } - } - - free(keys); -} - -void -p11t_rsa_tests(void) -{ - p11t_slot_for_each_mech(CKM_RSA_PKCS, test_rsa_pkcs); -} diff --git a/src/rsa.c b/src/rsa.c new file mode 100644 index 0000000..2a343d6 --- /dev/null +++ b/src/rsa.c @@ -0,0 +1,420 @@ + +#include "config.h" + +#include "p11-tests.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void +test_rsa_decrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type, RSA* rsa) +{ + CK_BYTE encrypted[p11t_test_data_size]; + CK_BYTE decrypted[p11t_test_data_size]; + CK_MECHANISM mech; + const CK_BYTE* data; + CK_ULONG n_data, n_decrypted; + int size, n_encrypted; + CK_RV rv; + + /** C_Decrypt */ + + data = p11t_test_data; + n_data = p11t_test_data_size; + + size = RSA_size(rsa); + assert(size); + assert(size < sizeof(encrypted)); + assert(size < sizeof(decrypted)); + assert(size < n_data); + + switch(mech_type) + { + case CKM_RSA_PKCS: + /** - CKM_RSA_PKCS */ + n_data = size - 11; + n_encrypted = RSA_public_encrypt(n_data, data, encrypted, rsa, RSA_PKCS1_PADDING); + assert(n_encrypted == size); + break; + case CKM_RSA_X_509: + /** - CKM_RSA_X_509 */ + n_data = size; + n_encrypted = RSA_public_encrypt(n_data, data, encrypted, rsa, RSA_NO_PADDING); + assert(n_encrypted == size); + break; + default: + return; + }; + + mech.mechanism = mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = (p11t_module_funcs->C_DecryptInit)(session, &mech, key); + p11t_check_returns("C_DecryptInit: rsa", rv, CKR_OK); + + n_decrypted = sizeof(decrypted); + rv = (p11t_module_funcs->C_Decrypt)(session, encrypted, n_encrypted, decrypted, &n_decrypted); + p11t_check_returns("C_Decrypt: rsa", rv, CKR_OK); + + if(n_decrypted != n_data) + p11t_check_fail("C_Decrypt: rsa decrypt failed, wrong length"); + if(memcmp(data, decrypted, n_data) != 0) + p11t_check_fail("C_Decrypt: rsa decrypt failed, bad data"); +} + +static void +hash_for_rsa_ssl3_sign(const CK_BYTE* data, CK_ULONG n_data, + CK_BYTE_PTR output, CK_ULONG_PTR n_output) +{ + assert(*n_output >= MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH); + MD5(data, n_data, output); + SHA1(data, n_data, output + MD5_DIGEST_LENGTH); + *n_output = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH; +} + +static void +hash_for_rsa_pkcs_sign(int algo, int wrap, const CK_BYTE* data, + CK_ULONG n_data, CK_BYTE_PTR output, CK_ULONG_PTR n_output) +{ + CK_BYTE hash[EVP_MAX_MD_SIZE]; + X509_SIG sig; + X509_ALGOR algor; + ASN1_TYPE parameter; + ASN1_OCTET_STRING digest; + EVP_MD_CTX ctx; + const EVP_MD* evp; + size_t n_hash; + int val; + + if(algo == NID_md5_sha1) + { + hash_for_rsa_ssl3_sign(data, n_data, output, n_output); + return; + } + + evp = EVP_get_digestbynid(algo); + assert(evp); + + val = EVP_DigestInit(&ctx, evp); + assert(val >= 0); + EVP_DigestUpdate(&ctx, data, n_data); + EVP_DigestFinal(&ctx, hash, &n_hash); + + /* Not wrapping? */ + if(!wrap) + { + assert(*n_output >= n_hash); + *n_output = n_hash; + memcpy(output, hash, n_hash); + return; + } + + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(algo); + assert(sig.algor->algorithm); + assert(sig.algor->algorithm->length); + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = hash; + sig.digest->length = n_hash; + + val = i2d_X509_SIG(&sig, &output); + assert(*n_output >= val); + *n_output = val; +} + +static void +test_rsa_pkcs_sign_hash(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + RSA* rsa, int algo) +{ + CK_BYTE hash[p11t_test_data_size]; + CK_BYTE sig[p11t_test_data_size]; + CK_MECHANISM mech; + CK_ULONG n_hash, n_sig; + CK_RV rv; + int res; + + /* Hash the data with appropriate wrappers */ + n_hash = sizeof(hash); + hash_for_rsa_pkcs_sign(algo, 1, p11t_test_data, p11t_test_data_size, hash, &n_hash); + + mech.mechanism = CKM_RSA_PKCS; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = (p11t_module_funcs->C_SignInit)(session, &mech, key); + p11t_check_returns("C_SignInit: rsa pkcs", rv, CKR_OK); + + n_sig = sizeof(sig); + rv = (p11t_module_funcs->C_Sign)(session, hash, n_hash, sig, &n_sig); + p11t_check_returns("C_Sign: rsa pkcs", rv, CKR_OK); + + /* Hash the data again this time without wrapping */ + n_hash = sizeof(hash); + hash_for_rsa_pkcs_sign(algo, 0, p11t_test_data, p11t_test_data_size, hash, &n_hash); + + /* Verify the signature */ + res = RSA_verify(algo, hash, n_hash, sig, n_sig, rsa); + if(res != 1) + p11t_check_fail("C_Sign: rsa pkcs signature did not verify"); +} + +static void +test_rsa_x509_sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, RSA* rsa) +{ + const CK_BYTE* data; + CK_BYTE sig[p11t_test_data_size]; + CK_BYTE check[p11t_test_data_size]; + CK_MECHANISM mech; + CK_ULONG n_data, n_sig; + CK_RV rv; + int res, size; + + size = RSA_size(rsa); + data = p11t_test_data; + n_data = size / 2; + assert(n_data <= p11t_test_data_size); + + mech.mechanism = CKM_RSA_X_509; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = (p11t_module_funcs->C_SignInit)(session, &mech, key); + p11t_check_returns("C_SignInit: rsa x509", rv, CKR_OK); + + n_sig = sizeof(sig); + rv = (p11t_module_funcs->C_Sign)(session, (CK_BYTE*)data, n_data, sig, &n_sig); + p11t_check_returns("C_Sign: rsa x509", rv, CKR_OK); + p11t_check_ulong("C_Sign: rsa x509 result length", n_sig, size); + + res = RSA_public_decrypt(n_sig, sig, check, rsa, RSA_NO_PADDING); + if(res < 0) + p11t_check_fail("C_Sign: rsa x509 signature was invalid"); + + assert(res > n_data); + if(memcmp(check + (res - n_data), data, n_data) != 0) + p11t_check_fail("C_Sign: rsa x509 signature did not verify"); +} + +static void +test_rsa_sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type, RSA* rsa) +{ + /** C_Sign */ + + switch(mech_type) + { + case CKM_RSA_PKCS: + /** - CKM_RSA_PKCS (SHA1) */ + test_rsa_pkcs_sign_hash(session, key, rsa, NID_sha1); + /** - CKM_RSA_PKCS (MD5) */ + test_rsa_pkcs_sign_hash(session, key, rsa, NID_md5); + /** - CKM_RSA_PKCS (SHA1/MD5/SSL3) */ + test_rsa_pkcs_sign_hash(session, key, rsa, NID_md5_sha1); + break; + case CKM_RSA_X_509: + test_rsa_x509_sign(session, key, rsa); + break; + default: + return; + }; +} + +static void +test_rsa_private_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type) +{ + CK_ATTRIBUTE attrs[2]; + CK_BBOOL can_decrypt = 0; + CK_BBOOL can_sign = 0; + RSA *rsa; + + attrs[0].type = CKA_DECRYPT; + attrs[0].ulValueLen = sizeof(CK_BBOOL); + attrs[0].pValue = &can_decrypt; + attrs[1].type = CKA_SIGN; + attrs[1].ulValueLen = sizeof(CK_BBOOL); + attrs[1].pValue = &can_sign; + + if(!p11t_object_get(session, key, attrs, 2)) + return; + + rsa = p11t_key_export_public_rsa(session, key); + if(!rsa) + return; + + if(can_decrypt) + test_rsa_decrypt(session, key, mech_type, rsa); + + if(can_sign) + test_rsa_sign(session, key, mech_type, rsa); + + RSA_free(rsa); +} + +static void +test_rsa_encrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type, RSA* rsa) +{ + CK_BYTE encrypted[p11t_test_data_size]; + CK_BYTE check[p11t_test_data_size]; + CK_OBJECT_HANDLE privkey; + CK_MECHANISM mech; + const CK_BYTE* data; + CK_ULONG n_data, n_check, n_encrypted; + int size; + CK_RV rv; + + data = p11t_test_data; + n_data = p11t_test_data_size; + + /** C_Encrypt */ + + size = RSA_size(rsa); + assert(size); + assert(size < sizeof(encrypted)); + assert(size < sizeof(check)); + assert(size < n_data); + + switch(mech_type) + { + case CKM_RSA_PKCS: + /** - CKM_RSA_PKCS */ + n_data = size - 11; + break; + case CKM_RSA_X_509: + /** - CKM_RSA_X_509 */ + n_data = size; + break; + default: + return; + }; + + mech.mechanism = mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* Now ask PKCS#11 to decrypt it */ + rv = (p11t_module_funcs->C_EncryptInit)(session, &mech, key); + p11t_check_returns("C_EncryptInit: rsa", rv, CKR_OK); + + n_encrypted = sizeof(encrypted); + rv = (p11t_module_funcs->C_Encrypt)(session, (CK_BYTE*)data, n_data, encrypted, &n_encrypted); + p11t_check_returns("C_Encrypt: rsa", rv, CKR_OK); + + if(size != n_encrypted) + p11t_check_fail("C_Encrypt: rsa encrypt failed, wrong length"); + + /* We need to find a private key in order to validate */ + privkey = p11t_key_get_private(session, key); + if(privkey == CK_INVALID) + return; + + rv = (p11t_module_funcs->C_DecryptInit)(session, &mech, privkey); + p11t_check_returns("C_DecryptInit: rsa validate", rv, CKR_OK); + + n_check = sizeof(check); + rv = (p11t_module_funcs->C_Decrypt)(session, encrypted, n_encrypted, check, &n_check); + p11t_check_returns("C_Decrypt: rsa validate", rv, CKR_OK); + + if(n_check != n_data) + p11t_check_fail("C_Decrypt: rsa validate failed, wrong length"); + if(memcmp(data, check, n_data) != 0) + p11t_check_fail("C_Decrypt: rsa validate failed, bad data"); +} + +static void +test_rsa_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, + CK_MECHANISM_TYPE mech_type) +{ + CK_ATTRIBUTE attrs[2]; + CK_BBOOL can_encrypt = 0; + CK_BBOOL can_verify = 0; + RSA *rsa; + + attrs[0].type = CKA_ENCRYPT; + attrs[0].ulValueLen = sizeof(CK_BBOOL); + attrs[0].pValue = &can_encrypt; + attrs[1].type = CKA_VERIFY; + attrs[1].ulValueLen = sizeof(CK_BBOOL); + attrs[1].pValue = &can_verify; + + if(!p11t_object_get(session, key, attrs, 2)) + return; + + rsa = p11t_key_export_public_rsa(session, key); + if(!rsa) + return; + + if(can_encrypt) + test_rsa_encrypt(session, key, mech_type, rsa); + + RSA_free(rsa); +} + +static void +test_rsa_pkcs(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_RSA; + 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_rsa_private_key(session, keys[i], mech); + else if(klass == CKO_PUBLIC_KEY) + test_rsa_public_key(session, keys[i], mech); + } + } + + free(keys); +} + +void +p11t_rsa_tests(void) +{ + OpenSSL_add_all_digests(); + p11t_slot_for_each_mech(CKM_RSA_PKCS, test_rsa_pkcs); +} -- cgit v1.2.3