summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-11-30 21:58:21 +0100
committerMiloslav Trmač <mitr@redhat.com>2010-11-30 21:59:46 +0100
commit9f8c85856ca06788c4eedb16d37f375491948a54 (patch)
treeca7cc58d3eebf6cc4fa2c268cc7be061021951ac
parentbd1167732c75a89ad816af878772c0925befc449 (diff)
downloadncrypto-9f8c85856ca06788c4eedb16d37f375491948a54.tar.gz
ncrypto-9f8c85856ca06788c4eedb16d37f375491948a54.tar.xz
ncrypto-9f8c85856ca06788c4eedb16d37f375491948a54.zip
Use PKCS#8 privateKeyInfo for private keys in DER form
-rw-r--r--include/ncrypto/ncrypto.h3
-rw-r--r--lib/ncrypto_nss.c177
2 files changed, 94 insertions, 86 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index 3938b45..07e57be 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -77,7 +77,8 @@ CK_RV ncr_public_key_create (struct ncr_public_key **key, const void *der,
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);
-/* "Sensitive" corresponds to CKA_SENSITIVE. */
+/* The PKCS#8 privateKeyInfo structure is used for private keys. "Sensitive"
+ corresponds to CKA_SENSITIVE. */
CK_RV ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
_Bool sensitive, const void *der, size_t der_size,
const void *public_value,
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index 4c5ac06..afdc5b0 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -254,67 +254,30 @@ ncr_public_key_destroy (struct ncr_public_key *key)
return CKR_OK;
}
+/* Create a private key based on a PKCS#8 privateKeyInfo DER_PKI. */
static CK_RV
private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
- bool sensitive, const SECItem *der_key,
+ bool sensitive, const SECItem *der_pki,
const SECItem *public_value)
{
static const uint8_t wrap_key[32]; /* = { 0, }; */
static const uint8_t wrap_iv[16]; /* = { 0, }; */
- static const uint8_t zero; /* = 0; */
struct ncr_private_key *k;
- struct private_key_info der_input;
PK11SlotInfo *slot;
- SECItem der_info, *der_res, key_item, iv_item, wrapped_item;
- SECOidTag alg_tag;
+ SECItem key_item, iv_item, wrapped_item;
SECStatus ss;
PK11SymKey *wrapping_key;
PK11Context *ctx;
int wrapped_len;
- switch (type)
- {
- case CKK_RSA:
- alg_tag = SEC_OID_PKCS1_RSA_ENCRYPTION;
- break;
-
- default:
- g_return_val_if_reached (CKR_ARGUMENTS_BAD);
- }
-
k = malloc (sizeof (*k));
if (k == NULL)
return CKR_HOST_MEMORY;
- der_input.version.type = siUnsignedInteger;
- der_input.version.data = (void *)&zero;
- der_input.version.len = sizeof (zero);
- memset (&der_input.algorithm, 0, sizeof (der_input.algorithm));
- if (SECOID_SetAlgorithmID (NULL, &der_input.algorithm, alg_tag, NULL)
- != SECSuccess)
- {
- free (k);
- return CKR_GENERAL_ERROR;
- }
- der_input.private_key = *der_key;
-
- der_info.data = NULL;
- der_info.len = 0;
- der_res = SEC_ASN1EncodeItem (NULL, &der_info, &der_input,
- private_key_info_asn1_template);
-
- SECOID_DestroyAlgorithmID (&der_input.algorithm, PR_FALSE);
-
- if (der_res == NULL)
- {
- free (k);
- return CKR_HOST_MEMORY;
- }
-
slot = PK11_GetBestSlot (CKM_AES_CBC_PAD, NULL);
if (slot == NULL)
- goto err_der_info;
+ return CKR_GENERAL_ERROR;
key_item.data = (void *)wrap_key;
key_item.len = sizeof (wrap_key);
@@ -333,13 +296,13 @@ private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
if (ctx == NULL)
goto err_wrapping_key;
memset (&wrapped_item, 0, sizeof (wrapped_item));
- if (SECITEM_AllocItem (NULL, &wrapped_item, der_info.len + 16) == NULL)
+ if (SECITEM_AllocItem (NULL, &wrapped_item, der_pki->len + 16) == NULL)
{
PK11_DestroyContext (ctx, PR_TRUE);
goto err_wrapping_key;
}
if (PK11_CipherOp (ctx, wrapped_item.data, &wrapped_len, wrapped_item.len,
- der_info.data, der_info.len) != SECSuccess)
+ der_pki->data, der_pki->len) != SECSuccess)
{
PK11_DestroyContext (ctx, PR_TRUE);
goto err_wrapped_item;
@@ -359,7 +322,6 @@ private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
PK11_FreeSymKey (wrapping_key);
PK11_FreeSlot (slot);
- PORT_Free (der_info.data);
if (k->key == NULL)
goto err_k;
@@ -374,16 +336,47 @@ private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
PK11_FreeSymKey (wrapping_key);
err_slot:
PK11_FreeSlot (slot);
- err_der_info:
- PORT_Free (der_info.data);
err_k:
free (k);
return CKR_GENERAL_ERROR;
}
+/* Create a private key based on INPUT_PKI.
+ PKI->version is ignored. */
+static CK_RV
+private_key_create_components (struct ncr_private_key **key, CK_KEY_TYPE type,
+ bool sensitive,
+ const struct private_key_info *input_pki,
+ const SECItem *public_value)
+{
+ static const uint8_t zero; /* = 0; */
+
+ struct private_key_info pki;
+ SECItem der_pki;
+ CK_RV res;
+
+ pki.version.type = siUnsignedInteger;
+ pki.version.data = (void *)&zero;
+ pki.version.len = sizeof (zero);
+ pki.algorithm = input_pki->algorithm;
+ pki.private_key = input_pki->private_key;
+
+ der_pki.data = NULL;
+ der_pki.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &der_pki, &pki, private_key_info_asn1_template)
+ == NULL)
+ return CKR_HOST_MEMORY;
+
+ res = private_key_create (key, type, sensitive, &der_pki, public_value);
+
+ SECITEM_ZfreeItem (&der_pki, PR_FALSE);
+ return res;
+}
+
+/* Set DER_PKI to a PKCS#8 privateKeyInfo describing KEY. */
static CK_RV
private_key_export (struct ncr_private_key *key, PRArenaPool *arena,
- SECItem *der_key)
+ SECItem *der_pki)
{
static const uint8_t wrap_key[32]; /* = { 0, }; */
static const uint8_t wrap_iv[16]; /* = { 0, }; */
@@ -393,7 +386,6 @@ private_key_export (struct ncr_private_key *key, PRArenaPool *arena,
PK11SymKey *wrapping_key;
PK11Context *ctx;
int der_info_len;
- struct private_key_info der_output;
SECStatus ss;
CK_RV res;
@@ -471,25 +463,8 @@ private_key_export (struct ncr_private_key *key, PRArenaPool *arena,
}
der_info.len += der_info_len;
- /* "type" is accessed by the decoder for ASN1_INTEGER */
- der_output.version.type = siUnsignedInteger;
- if (SEC_QuickDERDecodeItem (arena, &der_output,
- private_key_info_asn1_template, &der_info)
- != SECSuccess)
- {
- res = CKR_GENERAL_ERROR;
- goto err_wrapped_item;
- }
-
- /* Should we validate the version and algorithm ID here? */
-
- *der_key = der_output.private_key;
-
- SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
- PK11_FreeSymKey (wrapping_key);
- PK11_FreeSlot (slot);
-
- return CKR_OK;
+ *der_pki = der_info;
+ res = CKR_OK;
err_wrapped_item:
SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
@@ -500,6 +475,27 @@ private_key_export (struct ncr_private_key *key, PRArenaPool *arena,
return res;
}
+/* Fill PKI with info from KEY. */
+static CK_RV
+private_key_export_components (struct ncr_private_key *key, PRArenaPool *arena,
+ struct private_key_info *pki)
+{
+ SECItem der_pki;
+ CK_RV res;
+
+ res = private_key_export (key, arena, &der_pki);
+ if (res != CKR_OK)
+ return res;
+
+ /* "type" is accessed by the decoder for ASN1_INTEGER */
+ pki->version.type = siUnsignedInteger;
+ if (SEC_QuickDERDecodeItem (arena, pki, private_key_info_asn1_template,
+ &der_pki) != SECSuccess)
+ return CKR_GENERAL_ERROR;
+
+ return CKR_OK;
+}
+
/* FIXME: public_value should not be necessary, it is somewhere inside "der". */
CK_RV
ncr_private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
@@ -555,7 +551,7 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
size_t *dest_size_ptr)
{
PRArenaPool *arena;
- SECItem der_key;
+ SECItem der_pki;
CK_RV res;
res = ensure_ncr_is_open ();
@@ -570,25 +566,25 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
if (arena == NULL)
return CKR_HOST_MEMORY;
- res = private_key_export (key, arena, &der_key);
+ res = private_key_export (key, arena, &der_pki);
if (res != CKR_OK)
goto end;
if (dest == NULL)
{
- *dest_size_ptr = der_key.len;
+ *dest_size_ptr = der_pki.len;
res = CKR_OK;
goto end;
}
- if (*dest_size_ptr < der_key.len)
+ if (*dest_size_ptr < der_pki.len)
{
- *dest_size_ptr = der_key.len;
+ *dest_size_ptr = der_pki.len;
res = CKR_BUFFER_TOO_SMALL;
goto end;
}
- *dest_size_ptr = der_key.len;
+ *dest_size_ptr = der_pki.len;
- memcpy (dest, der_key.data, der_key.len);
+ memcpy (dest, der_pki.data, der_pki.len);
res = CKR_OK;
end:
@@ -895,7 +891,7 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive,
static const uint8_t zero; /* = 0; */
struct rsa_private_key der_input;
- SECItem der_key;
+ struct private_key_info pki;
CK_RV res;
res = ensure_ncr_is_open ();
@@ -907,19 +903,30 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive,
if (res != CKR_OK)
return res;
+ memset (&pki.algorithm, 0, sizeof (pki.algorithm));
+ if (SECOID_SetAlgorithmID (NULL, &pki.algorithm, SEC_OID_PKCS1_RSA_ENCRYPTION,
+ NULL) != SECSuccess)
+ return CKR_GENERAL_ERROR;
+
der_input.version.type = siUnsignedInteger;
der_input.version.data = (void *)&zero;
der_input.version.len = sizeof (zero);
- der_key.data = NULL;
- der_key.len = 0;
- if (SEC_ASN1EncodeItem (NULL, &der_key, &der_input,
+ pki.private_key.data = NULL;
+ pki.private_key.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &pki.private_key, &der_input,
rsa_private_key_asn1_template) == NULL)
- return CKR_HOST_MEMORY;
+ {
+ res = CKR_HOST_MEMORY;
+ goto end_algorithm;
+ }
- res = private_key_create (key, CKK_RSA, sensitive, &der_key,
- &der_input.items[NCR_RSA_PRIVATE_MPI_MODULUS]);
- PORT_Free (der_key.data);
+ res = private_key_create_components
+ (key, CKK_RSA, sensitive, &pki,
+ &der_input.items[NCR_RSA_PRIVATE_MPI_MODULUS]);
+ SECITEM_ZfreeItem (&pki.private_key, PR_FALSE);
+ end_algorithm:
+ SECOID_DestroyAlgorithmID (&pki.algorithm, PR_FALSE);
return res;
}
@@ -928,9 +935,9 @@ ncr_private_key_export_rsa (struct ncr_private_key *key,
struct ncr_mpi
mpis[static NCR_RSA_PRIVATE_NUM_MPIS])
{
+ struct private_key_info pki;
struct rsa_private_key der_output;
PRArenaPool *arena;
- SECItem der_key;
CK_RV res;
size_t i;
@@ -946,7 +953,7 @@ ncr_private_key_export_rsa (struct ncr_private_key *key,
if (arena == NULL)
return CKR_HOST_MEMORY;
- res = private_key_export (key, arena, &der_key);
+ res = private_key_export_components (key, arena, &pki);
if (res != CKR_OK)
goto end;
@@ -955,7 +962,7 @@ ncr_private_key_export_rsa (struct ncr_private_key *key,
for (i = 0; i < NCR_RSA_PRIVATE_NUM_MPIS; i++)
der_output.items[i].type = siUnsignedInteger;
if (SEC_QuickDERDecodeItem (arena, &der_output, rsa_private_key_asn1_template,
- &der_key) != SECSuccess)
+ &pki.private_key) != SECSuccess)
{
res = CKR_GENERAL_ERROR;
goto end;