From 012b4861d820dfd954dcd3563b6366812a30205f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Thu, 25 Nov 2010 18:07:25 +0100 Subject: Add ncr_public_key_export --- include/ncrypto/ncrypto.h | 2 ++ lib/ncrypto_nss.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) 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 @@ -145,6 +145,92 @@ 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) +{ + 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) -- cgit