summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2008-12-05 22:48:19 +0000
committerStef Walter <stef@memberwebs.com>2008-12-05 22:48:19 +0000
commit746579baf9176eb13dc19e98627e27e900c9859d (patch)
tree387d83ddbd2ae25836f27594613bfa2919807a44
parent9bf245ea2afb75c4180d7fac707bb0c1bcb6b17d (diff)
Implement RSA sign tests.
-rw-r--r--doc/pkcs11-coverage.txt5
-rw-r--r--src/Makefile.am2
-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 = &parameter;
+ 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);
}