diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-11-25 18:43:58 +0100 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-11-25 23:08:50 +0100 |
commit | 4c7d02965c0ad914068eb9edd65b5d918ffbf7be (patch) | |
tree | 4de6425356a0db868617e0b1c09e22353354ca3f | |
parent | 012b4861d820dfd954dcd3563b6366812a30205f (diff) | |
download | ncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.tar.gz ncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.tar.xz ncrypto-4c7d02965c0ad914068eb9edd65b5d918ffbf7be.zip |
Add ncr_public_key_export_rsa().
-rw-r--r-- | include/ncrypto/ncrypto.h | 6 | ||||
-rw-r--r-- | lib/ncrypto_nss.c | 192 | ||||
-rw-r--r-- | tests/rsa.c | 14 |
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); |