summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/ncrypto/ncrypto.h5
-rw-r--r--lib/ncrypto_nss.c191
2 files changed, 89 insertions, 107 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index d9508bf..3938b45 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -71,8 +71,9 @@ CK_RV ncr_symm_key_destroy (struct ncr_symm_key *key);
struct ncr_public_key;
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);
+/* The X.509v3 subjectPublicKeyInfo structure is used for public keys. */
+CK_RV ncr_public_key_create (struct ncr_public_key **key, 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);
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index 4737fc2..e22c65a 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -151,8 +151,7 @@ static const SEC_ASN1Template private_key_info_asn1_template[] =
};
static CK_RV
-public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
- const SECItem *der_key)
+public_key_create (struct ncr_public_key **key, CERTSubjectPublicKeyInfo *spki)
{
struct ncr_public_key *k;
@@ -160,7 +159,7 @@ public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
if (k == NULL)
return CKR_HOST_MEMORY;
- k->key = SECKEY_ImportDERPublicKey((SECItem *)der_key, type);
+ k->key = SECKEY_ExtractPublicKey (spki);
if (k->key == NULL)
{
free (k);
@@ -171,62 +170,13 @@ public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
return CKR_OK;
}
-/* The caller is responsible for freeing der_spki. */
-static CK_RV
-public_key_export (struct ncr_public_key *key, PRArenaPool *arena,
- void **der_key, size_t *der_key_size, SECItem **der_spki_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;
- SECItem *der_spki;
-
- g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
-
- der_spki = SECKEY_EncodeDERSubjectPublicKeyInfo (key->key);
- if (der_spki == NULL)
- return CKR_GENERAL_ERROR;
-
- if (SEC_QuickDERDecodeItem (arena, &der_output, asn1_template, der_spki)
- != SECSuccess)
- {
- SECITEM_FreeItem (der_spki, PR_TRUE);
- return CKR_GENERAL_ERROR;
- }
-
- *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_. */
- *der_key_size = (der_output.pub_key.len / 8
- + (der_output.pub_key.len % 8 != 0));
- *der_spki_ptr = der_spki;
- return CKR_OK;
-}
-
CK_RV
-ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
- const void *der, size_t der_size)
+ncr_public_key_create (struct ncr_public_key **key, const void *der,
+ size_t der_size)
{
- CK_RV res;
+ CERTSubjectPublicKeyInfo *spki;
SECItem der_key;
+ CK_RV res;
res = ensure_ncr_is_open ();
if (res != CKR_OK)
@@ -237,56 +187,53 @@ ncr_public_key_create (struct ncr_public_key **key, CK_KEY_TYPE type,
der_key.data = (void *)der;
der_key.len = der_size;
- return public_key_create (key, type, &der_key);
+ spki = SECKEY_DecodeDERSubjectPublicKeyInfo (&der_key);
+ if (spki == NULL)
+ return CKR_GENERAL_ERROR;
+
+ res = public_key_create (key, spki);
+
+ SECKEY_DestroySubjectPublicKeyInfo (spki);
+ 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;
+ SECItem *der;
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);
- /* 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)
- return CKR_HOST_MEMORY;
-
- res = public_key_export (key, arena, &der_key, &der_key_size, &der_spki);
- if (res != CKR_OK)
- goto end_arena;
+ der = SECKEY_EncodeDERSubjectPublicKeyInfo (key->key);
+ if (der == NULL)
+ return CKR_GENERAL_ERROR;
if (dest == NULL)
{
- *dest_size_ptr = der_key_size;
+ *dest_size_ptr = der->len;
res = CKR_OK;
- goto end_der_spki;
+ goto end_der;
}
- if (*dest_size_ptr < der_key_size)
+ if (*dest_size_ptr < der->len)
{
- *dest_size_ptr = der_key_size;
+ *dest_size_ptr = der->len;
res = CKR_BUFFER_TOO_SMALL;
- goto end_der_spki;
+ goto end_der;
}
- *dest_size_ptr = der_key_size;
+ *dest_size_ptr = der->len;
- memcpy (dest, der_key, der_key_size);
+ memcpy (dest, der->data, der->len);
res = CKR_OK;
- end_der_spki:
- SECITEM_FreeItem (der_spki, PR_TRUE);
- end_arena:
- PORT_FreeArena (arena, PR_FALSE);
+ end_der:
+ SECITEM_FreeItem (der, PR_TRUE);
return res;
}
@@ -821,7 +768,7 @@ ncr_public_key_create_rsa (struct ncr_public_key **key,
mpis[static NCR_RSA_PUBLIC_NUM_MPIS])
{
struct rsa_public_key der_input;
- SECItem der_key;
+ CERTSubjectPublicKeyInfo spki;
CK_RV res;
res = ensure_ncr_is_open ();
@@ -833,14 +780,33 @@ ncr_public_key_create_rsa (struct ncr_public_key **key,
if (res != CKR_OK)
return res;
- der_key.data = NULL;
- der_key.len = 0;
- if (SEC_ASN1EncodeItem(NULL, &der_key, &der_input,
+ spki.subjectPublicKey.data = NULL;
+ spki.subjectPublicKey.len = 0;
+ if (SEC_ASN1EncodeItem(NULL, &spki.subjectPublicKey, &der_input,
rsa_public_key_asn1_template) == NULL)
return CKR_HOST_MEMORY;
+ /* spki->subjectPublicKey is encoded as BIT_STRING, so "len" needs to be a
+ number of _bits_. */
+ if (spki.subjectPublicKey.len > UINT_MAX / 8)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_subjectPublicKey;
+ }
+ spki.subjectPublicKey.len *= 8;
- res = public_key_create (key, CKK_RSA, &der_key);
- PORT_Free (der_key.data);
+ memset (&spki.algorithm, 0, sizeof (spki.algorithm));
+ if (SECOID_SetAlgorithmID (NULL, &spki.algorithm,
+ SEC_OID_PKCS1_RSA_ENCRYPTION, NULL) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_subjectPublicKey;
+ }
+
+ res = public_key_create (key, &spki);
+
+ SECOID_DestroyAlgorithmID (&spki.algorithm, PR_FALSE);
+ end_subjectPublicKey:
+ PORT_Free (spki.subjectPublicKey.data);
return res;
}
@@ -849,11 +815,15 @@ CK_RV
ncr_public_key_export_rsa (struct ncr_public_key *key,
struct ncr_mpi mpis[static NCR_RSA_PUBLIC_NUM_MPIS])
{
+ static const uint8_t asn1_null[] = { SEC_ASN1_NULL, 0 };
+ static const SECItem asn1_null_item
+ = { 0, (void *)&asn1_null, sizeof (asn1_null) };
+
struct rsa_public_key der_output;
+ CERTSubjectPublicKeyInfo *spki;
+ const SECOidData *oid;
PRArenaPool *arena;
- SECItem *der_spki, der_key_item;
- void *der_key;
- size_t der_key_size;
+ SECItem key_item;
CK_RV res;
size_t i;
@@ -861,42 +831,53 @@ ncr_public_key_export_rsa (struct ncr_public_key *key,
if (res != CKR_OK)
return res;
+ g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (mpis != NULL, CKR_ARGUMENTS_BAD);
+ spki = SECKEY_CreateSubjectPublicKeyInfo(key->key);
+ if (spki == NULL)
+ return CKR_GENERAL_ERROR;
+
+ oid = SECOID_FindOIDByTag (SEC_OID_PKCS1_RSA_ENCRYPTION);
+ if (oid == NULL
+ || !SECITEM_ItemsAreEqual(&spki->algorithm.algorithm, &oid->oid)
+ || !SECITEM_ItemsAreEqual(&spki->algorithm.parameters, &asn1_null_item))
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_spki;
+ }
+
/* 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)
- return CKR_HOST_MEMORY;
-
- res = public_key_export (key, arena, &der_key, &der_key_size, &der_spki);
- if (res != CKR_OK)
- goto end_arena;
-
- 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_der_spki;
+ res = CKR_HOST_MEMORY;
+ goto end_spki;
}
+
+ /* spki->subjectPublicKey is encoded as BIT_STRING, so "len" is a number of
+ _bits_. */
+ key_item.data = spki->subjectPublicKey.data;
+ key_item.len = (spki->subjectPublicKey.len / 8
+ + (spki->subjectPublicKey.len % 8 != 0));
/* Setting type to siUnsignedInteger requests removal of leading zeroes. */
for (i = 0; i < NCR_RSA_PUBLIC_NUM_MPIS; i++)
der_output.items[i].type = siUnsignedInteger;
if (SEC_QuickDERDecodeItem (arena, &der_output, rsa_public_key_asn1_template,
- &der_key_item) != SECSuccess)
+ &key_item) != SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_der_spki;
+ goto end_arena;
}
res = mpi_output_decoded_SECItems(mpis, der_output.items,
NCR_RSA_PUBLIC_NUM_MPIS);
- end_der_spki:
- SECITEM_FreeItem (der_spki, PR_TRUE);
end_arena:
PORT_FreeArena (arena, PR_FALSE);
+ end_spki:
+ SECKEY_DestroySubjectPublicKeyInfo (spki);
return res;
}