diff options
-rw-r--r-- | doc/pkcs11-coverage.txt | 5 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/rsa.c (renamed from src/rsa-pkcs.c) | 236 |
3 files changed, 209 insertions, 34 deletions
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.c index e97a3b0..2a343d6 100644 --- a/src/rsa-pkcs.c +++ b/src/rsa.c @@ -7,7 +7,13 @@ #include <stdlib.h> #include <string.h> -void +#include <openssl/evp.h> +#include <openssl/sha.h> +#include <openssl/md5.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +static void test_rsa_decrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE mech_type, RSA* rsa) { @@ -65,7 +71,199 @@ test_rsa_decrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, p11t_check_fail("C_Decrypt: rsa decrypt failed, bad data"); } -void +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) { @@ -136,36 +334,7 @@ test_rsa_encrypt(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, 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 +static void test_rsa_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, CK_MECHANISM_TYPE mech_type) { @@ -194,7 +363,7 @@ test_rsa_public_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key, RSA_free(rsa); } -void +static void test_rsa_pkcs(CK_SLOT_ID slot, CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info) { CK_SESSION_HANDLE session; @@ -246,5 +415,6 @@ test_rsa_pkcs(CK_SLOT_ID slot, CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR inf void p11t_rsa_tests(void) { + OpenSSL_add_all_digests(); p11t_slot_for_each_mech(CKM_RSA_PKCS, test_rsa_pkcs); } |