summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-11-25 18:43:58 +0100
committerMiloslav Trmač <mitr@redhat.com>2010-11-25 23:08:50 +0100
commit4c7d02965c0ad914068eb9edd65b5d918ffbf7be (patch)
tree4de6425356a0db868617e0b1c09e22353354ca3f
parent012b4861d820dfd954dcd3563b6366812a30205f (diff)
downloadncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.tar.gz
ncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.tar.xz
ncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.zip
Add ncr_public_key_export_rsa().
-rw-r--r--include/ncrypto/ncrypto.h6
-rw-r--r--lib/ncrypto_nss.c192
-rw-r--r--tests/rsa.c14
3 files changed, 166 insertions, 46 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index c4de81e..9f5a3f4 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -82,10 +82,16 @@ CK_RV ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
size_t public_value_size);
CK_RV ncr_private_key_destroy (struct ncr_private_key *key);
+ /* RSA keys */
+
CK_RV ncr_public_key_create_rsa (struct ncr_public_key **key,
const void *modulus, size_t modulus_size,
const void *public_exponent,
size_t public_exponent_size);
+CK_RV ncr_public_key_export_rsa (struct ncr_public_key *key,
+ void *modulus, size_t *modulus_size_ptr,
+ void *public_exponent,
+ size_t *public_exponent_size_ptr);
CK_RV ncr_private_key_create_rsa (struct ncr_private_key **key,
const void *modulus, size_t modulus_size,
const void *public_exponent,
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index 71f63bc..13eeb6e 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -145,9 +145,11 @@ public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
return CKR_OK;
}
-CK_RV
-ncr_public_key_export (struct ncr_public_key *key, void *dest,
- size_t *dest_size_ptr)
+/* The caller is responsible for freeing the arena and der_spki. */
+static CK_RV
+public_key_export (struct ncr_public_key *key, void **der_key,
+ size_t *der_key_size, PRArenaPool **arena_ptr,
+ SECItem **der_spki_ptr)
{
struct subject_pub_key_info
{
@@ -171,19 +173,13 @@ ncr_public_key_export (struct ncr_public_key *key, void *dest,
struct subject_pub_key_info der_output;
PRArenaPool *arena;
- SECItem *der_key;
- size_t dest_size;
+ SECItem *der_spki;
CK_RV res;
- res = ensure_ncr_is_open ();
- if (res != CKR_OK)
- return res;
-
g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
- g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
- der_key = SECKEY_EncodeDERSubjectPublicKeyInfo (key->key);
- if (der_key == NULL)
+ der_spki = SECKEY_EncodeDERSubjectPublicKeyInfo (key->key);
+ if (der_spki == NULL)
return CKR_GENERAL_ERROR;
/* Ugly... the PLArenaPool type is from NSPR, but NSS implementation accesses
@@ -192,42 +188,72 @@ ncr_public_key_export (struct ncr_public_key *key, void *dest,
if (arena == NULL)
{
res = CKR_HOST_MEMORY;
- goto end_der_key;
+ goto err_der_spki;
}
- if (SEC_QuickDERDecodeItem (arena, &der_output, asn1_template, der_key)
+ if (SEC_QuickDERDecodeItem (arena, &der_output, asn1_template, der_spki)
!= SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_arena;
+ goto err_arena;
}
+ *der_key = der_output.pub_key.data;
/* der_output.pub_key is encoded as BIT_STRING, so pub_key.len is a number of
_bits_. */
- dest_size = der_output.pub_key.len / 8;
- if (der_output.pub_key.len % 8 != 0)
- dest_size ++;
+ *der_key_size = (der_output.pub_key.len / 8
+ + (der_output.pub_key.len % 8 != 0));
+ *arena_ptr = arena;
+ *der_spki_ptr = der_spki;
+ return CKR_OK;
+
+ err_arena:
+ PORT_FreeArena (arena, PR_FALSE);
+ err_der_spki:
+ SECITEM_FreeItem (der_spki, PR_TRUE);
+ return res;
+}
+
+CK_RV
+ncr_public_key_export (struct ncr_public_key *key, void *dest,
+ size_t *dest_size_ptr)
+{
+ PRArenaPool *arena;
+ SECItem *der_spki;
+ void *der_key;
+ size_t der_key_size;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
+
+ res = public_key_export (key, &der_key, &der_key_size, &arena, &der_spki);
+ if (res != CKR_OK)
+ return res;
+
if (dest == NULL)
{
- *dest_size_ptr = dest_size;
+ *dest_size_ptr = der_key_size;
res = CKR_OK;
- goto end_arena;
+ goto end;
}
- if (*dest_size_ptr < dest_size)
+ if (*dest_size_ptr < der_key_size)
{
- *dest_size_ptr = dest_size;
+ *dest_size_ptr = der_key_size;
res = CKR_BUFFER_TOO_SMALL;
- goto end_arena;
+ goto end;
}
- *dest_size_ptr = dest_size;
+ *dest_size_ptr = der_key_size;
- memcpy (dest, der_output.pub_key.data, dest_size);
+ memcpy (dest, der_key, der_key_size);
res = CKR_OK;
- end_arena:
+ end:
PORT_FreeArena (arena, PR_FALSE);
- end_der_key:
- SECITEM_FreeItem (der_key, PR_TRUE);
+ SECITEM_FreeItem (der_spki, PR_TRUE);
return res;
}
@@ -453,26 +479,30 @@ ncr_private_key_destroy (struct ncr_private_key *key)
return CKR_OK;
}
+ /* RSA keys */
+
+struct rsa_public_key
+{
+ SECItem modulus, public_exponent;
+};
+
+static const SEC_ASN1Template rsa_public_key_asn1_template[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct rsa_public_key) },
+#define INT(X) { \
+ SEC_ASN1_INTEGER, offsetof (struct rsa_public_key, X), NULL, 0, \
+ }
+ INT (modulus), INT (public_exponent),
+#undef INT
+ { 0, 0, NULL, 0 }
+ };
+
CK_RV
ncr_public_key_create_rsa (struct ncr_public_key **key, const void *modulus,
size_t modulus_size, const void *public_exponent,
size_t public_exponent_size)
{
- struct rsa_pub_key
- {
- SECItem modulus, public_exponent;
- };
-
- static const SEC_ASN1Template asn1_template[] =
- {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct rsa_pub_key) },
-#define INT(X) { SEC_ASN1_INTEGER, offsetof (struct rsa_pub_key, X), NULL, 0, }
- INT (modulus), INT (public_exponent),
-#undef INT
- { 0, 0, NULL, 0 }
- };
-
- struct rsa_pub_key der_input;
+ struct rsa_public_key der_input;
SECItem der_key;
CK_RV res;
@@ -494,7 +524,8 @@ ncr_public_key_create_rsa (struct ncr_public_key **key, const void *modulus,
der_key.data = NULL;
der_key.len = 0;
- if (SEC_ASN1EncodeItem(NULL, &der_key, &der_input, asn1_template) == NULL)
+ if (SEC_ASN1EncodeItem(NULL, &der_key, &der_input,
+ rsa_public_key_asn1_template) == NULL)
return CKR_HOST_MEMORY;
res = public_key_create (key, CKK_RSA, &der_key);
@@ -504,6 +535,79 @@ ncr_public_key_create_rsa (struct ncr_public_key **key, const void *modulus,
}
CK_RV
+ncr_public_key_export_rsa (struct ncr_public_key *key, void *modulus,
+ size_t *modulus_size_ptr, void *public_exponent,
+ size_t *public_exponent_size_ptr)
+{
+ struct rsa_public_key der_output;
+ PRArenaPool *arena;
+ SECItem *der_spki, der_key_item;
+ void *der_key;
+ size_t der_key_size;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (modulus_size_ptr != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (public_exponent_size_ptr != NULL, CKR_ARGUMENTS_BAD);
+
+ res = public_key_export (key, &der_key, &der_key_size, &arena, &der_spki);
+ if (res != CKR_OK)
+ return res;
+
+ der_key_item.data = der_key;
+ der_key_item.len = der_key_size;
+ if (der_key_item.len != der_key_size)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end;
+ }
+ /* Setting type to siUnsignedInteger requests removal of leading zeroes. */
+ der_output.modulus.type = siUnsignedInteger;
+ der_output.public_exponent.type = siUnsignedInteger;
+ if (SEC_QuickDERDecodeItem (arena, &der_output, rsa_public_key_asn1_template,
+ &der_key_item) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end;
+ }
+
+ if (modulus == NULL || public_exponent == NULL)
+ {
+ *modulus_size_ptr = der_output.modulus.len;
+ *public_exponent_size_ptr = der_output.public_exponent.len;
+ res = CKR_OK;
+ goto end;
+ }
+ res = CKR_OK;
+ if (*modulus_size_ptr < der_output.modulus.len)
+ {
+ *modulus_size_ptr = der_output.modulus.len;
+ res = CKR_BUFFER_TOO_SMALL;
+ }
+ if (*public_exponent_size_ptr < der_output.public_exponent.len)
+ {
+ *public_exponent_size_ptr = der_output.public_exponent.len;
+ res = CKR_BUFFER_TOO_SMALL;
+ }
+ if (res != CKR_OK)
+ goto end;
+ *modulus_size_ptr = der_output.modulus.len;
+ *public_exponent_size_ptr = der_output.public_exponent.len;
+
+ memcpy (modulus, der_output.modulus.data, der_output.modulus.len);
+ memcpy (public_exponent, der_output.public_exponent.data,
+ der_output.public_exponent.len);
+
+ end:
+ PORT_FreeArena (arena, PR_FALSE);
+ SECITEM_FreeItem (der_spki, PR_TRUE);
+ return res;
+}
+
+CK_RV
ncr_private_key_create_rsa (struct ncr_private_key **key, const void *modulus,
size_t modulus_size, const void *public_exponent,
size_t public_exponent_size,
diff --git a/tests/rsa.c b/tests/rsa.c
index d14e05c..4e16769 100644
--- a/tests/rsa.c
+++ b/tests/rsa.c
@@ -49,8 +49,8 @@ main (void)
{
struct ncr_public_key *public;
struct ncr_private_key *private;
- uint8_t dest[4096];
- size_t src_size, dest_size;
+ uint8_t dest[4096], dest2[4096];
+ size_t src_size, dest_size, dest2_size;
CK_RV res;
/* Test key loading. Should we test the generic version as well? */
@@ -95,6 +95,16 @@ main (void)
sizeof (input));
assert (res != CKR_OK);
+ dest_size = sizeof (dest);
+ dest2_size = sizeof (dest2);
+ res = ncr_public_key_export_rsa (public, dest, &dest_size, dest2,
+ &dest2_size);
+ assert (res == CKR_OK);
+ assert (dest_size == sizeof (modulus));
+ assert (dest2_size == sizeof (public_exponent));
+ assert (memcmp (dest, modulus, dest_size) == 0);
+ assert (memcmp (dest2, public_exponent, dest2_size) == 0);
+
res = ncr_private_key_destroy (private);
assert (res == CKR_OK);