summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-11-25 18:07:25 +0100
committerMiloslav Trmač <mitr@redhat.com>2010-11-25 18:07:25 +0100
commit012b4861d820dfd954dcd3563b6366812a30205f (patch)
tree9919ddd6b62f25c914fd0c8493042923d181250a
parent3712df97eb0a1149823c6f0c6aace2ecfdb53f1b (diff)
downloadncrypto-012b4861d820dfd954dcd3563b6366812a30205f.tar.gz
ncrypto-012b4861d820dfd954dcd3563b6366812a30205f.tar.xz
ncrypto-012b4861d820dfd954dcd3563b6366812a30205f.zip
Add ncr_public_key_export
-rw-r--r--include/ncrypto/ncrypto.h2
-rw-r--r--lib/ncrypto_nss.c86
2 files changed, 88 insertions, 0 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index a09d451..c4de81e 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -73,6 +73,8 @@ struct ncr_private_key;
CK_RV ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
const void *der, size_t der_size);
+CK_RV ncr_public_key_export (struct ncr_public_key *key, void *dest,
+ size_t *dest_size_ptr);
CK_RV ncr_public_key_destroy (struct ncr_public_key *key);
CK_RV ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
const void *der, size_t der_size,
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index 2c806c4..71f63bc 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -146,6 +146,92 @@ public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
}
CK_RV
+ncr_public_key_export (struct ncr_public_key *key, void *dest,
+ size_t *dest_size_ptr)
+{
+ struct subject_pub_key_info
+ {
+ SECAlgorithmID algorithm;
+ SECItem pub_key;
+ };
+
+ static const SEC_ASN1Template asn1_template[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct subject_pub_key_info) },
+ {
+ SEC_ASN1_INLINE, offsetof (struct subject_pub_key_info, algorithm),
+ SECOID_AlgorithmIDTemplate, 0,
+ },
+ {
+ SEC_ASN1_BIT_STRING, offsetof (struct subject_pub_key_info, pub_key),
+ NULL, 0,
+ },
+ { 0, 0, NULL, 0 }
+ };
+
+ struct subject_pub_key_info der_output;
+ PRArenaPool *arena;
+ SECItem *der_key;
+ size_t dest_size;
+ 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)
+ return CKR_GENERAL_ERROR;
+
+ /* Ugly... the PLArenaPool type is from NSPR, but NSS implementation accesses
+ memory only initialized through NSS's PORT_* */
+ arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ {
+ res = CKR_HOST_MEMORY;
+ goto end_der_key;
+ }
+
+ if (SEC_QuickDERDecodeItem (arena, &der_output, asn1_template, der_key)
+ != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_arena;
+ }
+
+ /* 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 ++;
+ if (dest == NULL)
+ {
+ *dest_size_ptr = dest_size;
+ res = CKR_OK;
+ goto end_arena;
+ }
+ if (*dest_size_ptr < dest_size)
+ {
+ *dest_size_ptr = dest_size;
+ res = CKR_BUFFER_TOO_SMALL;
+ goto end_arena;
+ }
+ *dest_size_ptr = dest_size;
+
+ memcpy (dest, der_output.pub_key.data, dest_size);
+ res = CKR_OK;
+
+ end_arena:
+ PORT_FreeArena (arena, PR_FALSE);
+ end_der_key:
+ SECITEM_FreeItem (der_key, PR_TRUE);
+ return res;
+}
+
+CK_RV
ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
const void *der, size_t der_size)
{