summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-11-29 16:38:22 +0100
committerMiloslav Trmač <mitr@redhat.com>2010-11-29 16:38:22 +0100
commitcb0170516856f563e12d9ff79ad3333f641a2850 (patch)
tree94ba178f299fa686a269dc8442bd1d0bf59f2e36
parente7fa04556e265d65232d6ef2afc6c0c472198011 (diff)
downloadncrypto-cb0170516856f563e12d9ff79ad3333f641a2850.tar.gz
ncrypto-cb0170516856f563e12d9ff79ad3333f641a2850.tar.xz
ncrypto-cb0170516856f563e12d9ff79ad3333f641a2850.zip
Add RSA key generation
-rw-r--r--include/ncrypto/ncrypto.h5
-rw-r--r--lib/ncrypto_nss.c99
-rw-r--r--tests/rsa.c87
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č <mitr@redhat.com> */
#include <keyhi.h>
#include <nss.h>
#include <pk11pub.h>
+#include <secmodt.h>
#include <ncrypto/ncrypto.h>
@@ -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, &params);
+}
+
/* 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);