From cb0170516856f563e12d9ff79ad3333f641a2850 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 29 Nov 2010 16:38:22 +0100 Subject: Add RSA key generation --- include/ncrypto/ncrypto.h | 5 +++ lib/ncrypto_nss.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ tests/rsa.c | 87 ++++++++++++++++++++++++++++++----------- 3 files changed, 168 insertions(+), 23 deletions(-) diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h index 16d8258..d9508bf 100644 --- a/include/ncrypto/ncrypto.h +++ b/include/ncrypto/ncrypto.h @@ -130,6 +130,11 @@ CK_RV ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive, CK_RV ncr_private_key_export_rsa (struct ncr_private_key *key, struct ncr_mpi mpis[static NCR_RSA_PRIVATE_NUM_MPIS]); +CK_RV ncr_key_pair_generate_rsa (struct ncr_public_key **public_key, + struct ncr_private_key **private_key, + CK_MECHANISM_TYPE mech, _Bool sensitive, + CK_ULONG modulus_bits, + const struct ncr_mpi *public_exponent); /* Asymmetric operations */ diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c index dfd342c..818091d 100644 --- a/lib/ncrypto_nss.c +++ b/lib/ncrypto_nss.c @@ -33,6 +33,7 @@ Red Hat author: Miloslav Trmač */ #include #include #include +#include #include @@ -652,6 +653,52 @@ ncr_private_key_destroy (struct ncr_private_key *key) return CKR_OK; } +static CK_RV +key_pair_generate (struct ncr_public_key **public_key, + struct ncr_private_key **private_key, CK_MECHANISM_TYPE mech, + bool sensitive, void *params) +{ + struct ncr_public_key *pub; + struct ncr_private_key *priv; + PK11SlotInfo *slot; + + g_return_val_if_fail (public_key != NULL, CKR_ARGUMENTS_BAD); + g_return_val_if_fail (private_key != NULL, CKR_ARGUMENTS_BAD); + + pub = malloc (sizeof (*pub)); + if (pub == NULL) + return CKR_HOST_MEMORY; + priv = malloc (sizeof (*priv)); + if (priv == NULL) + { + free (pub); + return CKR_HOST_MEMORY; + } + + slot = PK11_GetBestSlot (mech, NULL); + if (slot == NULL) + goto err_priv; + + /* FIXME: propagate "sensitive" here? */ + priv->key = PK11_GenerateKeyPair(slot, mech, params, &pub->key, + PR_FALSE /* isPerm */, + PR_FALSE /* sensitive */, NULL); + PK11_FreeSlot (slot); + if (priv->key == NULL) + goto err_priv; + + + priv->sensitive = sensitive; + *public_key = pub; + *private_key = priv; + return CKR_OK; + + err_priv: + free (priv); + free (pub); + return CKR_GENERAL_ERROR; +} + /* Multi-precision integers */ /* Validate SRC and use it to set up DEST for ASN.1 encoding */ @@ -925,6 +972,58 @@ ncr_private_key_export_rsa (struct ncr_private_key *key, return res; } +CK_RV +ncr_key_pair_generate_rsa (struct ncr_public_key **public_key, + struct ncr_private_key **private_key, + CK_MECHANISM_TYPE mech, _Bool sensitive, + CK_ULONG modulus_bits, + const struct ncr_mpi *public_exponent) +{ + PK11RSAGenParams params; + CK_RV res; + + res = ensure_ncr_is_open (); + if (res != CKR_OK) + return res; + + switch (mech) + { + case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_X9_31_KEY_PAIR_GEN: + break; + + default: + g_return_val_if_reached (CKR_MECHANISM_INVALID); + } + + g_return_val_if_fail (modulus_bits <= INT_MAX, CKR_ARGUMENTS_BAD); + + params.keySizeInBits = modulus_bits; + if (public_exponent == NULL) + params.pe = 65537; + else + { + unsigned long val; + const uint8_t *p, *end; + + end = (const uint8_t *)public_exponent->data + public_exponent->size; + for (p = public_exponent->data; p < end && *p == 0; p++) + ; + g_return_val_if_fail ((size_t)(end - p) <= sizeof (val), + CKR_ARGUMENTS_BAD); + + val = 0; + while (p < end) + { + val = (val << 8) | *p; + p++; + } + params.pe = val; + } + + return key_pair_generate (public_key, private_key, mech, sensitive, ¶ms); +} + /* Asymmetric operations */ CK_RV diff --git a/tests/rsa.c b/tests/rsa.c index 2eeaa47..16f6012 100644 --- a/tests/rsa.c +++ b/tests/rsa.c @@ -65,32 +65,13 @@ validate_mpis (const struct ncr_mpi *mpis, size_t num_mpis) assert (memcmp (mpis[i].data, import_mpis[i].data, mpis[i].size) == 0); } -int -main (void) +static void +test_key_pair (struct ncr_public_key *public, struct ncr_private_key *private) { - struct ncr_public_key *public; - struct ncr_private_key *private; - struct ncr_mpi dest_mpis[NCR_RSA_PRIVATE_NUM_MPIS]; - uint8_t dest[4096], mpi_dest[NCR_RSA_PRIVATE_NUM_MPIS][256]; - size_t src_size, dest_size, i; + uint8_t dest[4096]; + size_t src_size, dest_size; CK_RV res; - /* We took a few shortcuts... validate them now. Note that these are NOT - guaranteed by the API. */ - assert ((size_t)NCR_RSA_PUBLIC_NUM_MPIS <= (size_t)NCR_RSA_PRIVATE_NUM_MPIS); - assert ((size_t)NCR_RSA_PUBLIC_MPI_MODULUS - == (size_t)NCR_RSA_PRIVATE_MPI_MODULUS); - assert ((size_t)NCR_RSA_PUBLIC_MPI_PUBLIC_EXPONENT - == (size_t)NCR_RSA_PRIVATE_MPI_PUBLIC_EXPONENT); - - - /* Test key loading. Should we test the generic version as well? */ - res = ncr_public_key_create_rsa (&public, import_mpis); - assert (res == CKR_OK); - res = ncr_private_key_create_rsa (&private, false, import_mpis); - assert (res == CKR_OK); - - /* Test encryption */ dest_size = sizeof (dest); res = ncr_public_key_encrypt (CKM_RSA_PKCS, public, dest, &dest_size, input, @@ -117,7 +98,36 @@ main (void) res = ncr_public_key_verify (CKM_RSA_PKCS, public, dest, dest_size, input, sizeof (input)); assert (res != CKR_OK); +} + +int +main (void) +{ + struct ncr_public_key *public; + struct ncr_private_key *private; + struct ncr_mpi dest_mpis[NCR_RSA_PRIVATE_NUM_MPIS]; + uint8_t mpi_dest[NCR_RSA_PRIVATE_NUM_MPIS][256]; + size_t i; + CK_RV res; + + /* We took a few shortcuts... validate them now. Note that these are NOT + guaranteed by the API. */ + assert ((size_t)NCR_RSA_PUBLIC_NUM_MPIS <= (size_t)NCR_RSA_PRIVATE_NUM_MPIS); + assert ((size_t)NCR_RSA_PUBLIC_MPI_MODULUS + == (size_t)NCR_RSA_PRIVATE_MPI_MODULUS); + assert ((size_t)NCR_RSA_PUBLIC_MPI_PUBLIC_EXPONENT + == (size_t)NCR_RSA_PRIVATE_MPI_PUBLIC_EXPONENT); + + + /* Test key loading. Should we test the generic version as well? */ + res = ncr_public_key_create_rsa (&public, import_mpis); + assert (res == CKR_OK); + res = ncr_private_key_create_rsa (&private, false, import_mpis); + assert (res == CKR_OK); + test_key_pair (public, private); + + /* Test key export. */ for (i = 0; i < NCR_RSA_PUBLIC_NUM_MPIS; i++) { dest_mpis[i].data = mpi_dest[i]; @@ -142,6 +152,37 @@ main (void) res = ncr_public_key_destroy (public); assert (res == CKR_OK); + + /* Test key generation. */ + res = ncr_key_pair_generate_rsa (&public, &private, CKM_RSA_PKCS_KEY_PAIR_GEN, + false, 1024, NULL); + assert (res == CKR_OK); + + test_key_pair (public, private); + + /* Test key export - only test that it succeeds. */ + for (i = 0; i < NCR_RSA_PUBLIC_NUM_MPIS; i++) + { + dest_mpis[i].data = mpi_dest[i]; + dest_mpis[i].size = sizeof (mpi_dest[i]); + } + res = ncr_public_key_export_rsa (public, dest_mpis); + assert (res == CKR_OK); + + for (i = 0; i < NCR_RSA_PRIVATE_NUM_MPIS; i++) + { + dest_mpis[i].data = mpi_dest[i]; + dest_mpis[i].size = sizeof (mpi_dest[i]); + } + res = ncr_private_key_export_rsa (private, dest_mpis); + assert (res == CKR_OK); + + res = ncr_private_key_destroy (private); + assert (res == CKR_OK); + + res = ncr_public_key_destroy (public); + assert (res == CKR_OK); + /* Test reference counting */ res = ncr_open (); assert (res == CKR_OK); -- cgit