summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-11-26 00:37:52 +0100
committerMiloslav Trmač <mitr@redhat.com>2010-11-26 00:37:52 +0100
commit6185079fd24c308530a4cebc66acc86dd7b40375 (patch)
tree2e39ae53285f55bbf57050d0f24f95c8fbe5d0fa /lib
parenteafbed071d3e3de75f8539c1473edd5a8af28cac (diff)
downloadncrypto-6185079fd24c308530a4cebc66acc86dd7b40375.tar.gz
ncrypto-6185079fd24c308530a4cebc66acc86dd7b40375.tar.xz
ncrypto-6185079fd24c308530a4cebc66acc86dd7b40375.zip
Add ncr_private_key_export_rsa ()
Diffstat (limited to 'lib')
-rw-r--r--lib/ncrypto_nss.c312
1 files changed, 217 insertions, 95 deletions
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index b6e7464..a925c48 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -445,53 +445,16 @@ private_key_create (struct ncr_private_key **key, CK_KEY_TYPE type,
return CKR_GENERAL_ERROR;
}
-/* 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,
- _Bool sensitive, const void *der, size_t der_size,
- const void *public_value, size_t public_value_size)
-{
- SECItem der_key;
- SECItem public;
- 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 (der != NULL, CKR_ARGUMENTS_BAD);
-
- der_key.data = (void *)der;
- der_key.len = der_size;
- public.data = (void *)public_value;
- public.len = public_value_size;
- return private_key_create (key, type, sensitive, &der_key, &public);
-}
-
-CK_RV
-ncr_private_key_set_sensitive (struct ncr_private_key *key)
-{
- CK_RV res;
-
- res = ensure_ncr_is_open ();
- if (res != CKR_OK)
- return res;
-
- g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
- key->sensitive = true;
- return CKR_OK;
-}
-
-CK_RV
-ncr_private_key_export (struct ncr_private_key *key, void *dest,
- size_t *dest_size_ptr)
+/* The caller is responsible for freeing the arena and der_info. */
+static CK_RV
+private_key_export (struct ncr_private_key *key, SECItem *der_key,
+ PRArenaPool **arena_ptr, SECItem *der_info)
{
static const uint8_t wrap_key[32]; /* = { 0, }; */
static const uint8_t wrap_iv[16]; /* = { 0, }; */
PK11SlotInfo *slot;
- SECItem key_item, iv_item, wrapped_item, der_info;
+ SECItem key_item, iv_item, wrapped_item;
PK11SymKey *wrapping_key;
PK11Context *ctx;
int der_info_len;
@@ -501,7 +464,6 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
CK_RV res;
g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
- g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
g_return_val_if_fail (!key->sensitive, CKR_ATTRIBUTE_SENSITIVE);
@@ -519,7 +481,7 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
if (wrapping_key == NULL)
{
res = CKR_GENERAL_ERROR;
- goto end_slot;
+ goto err_slot;
}
iv_item.data = (void *)wrap_iv;
iv_item.len = sizeof (wrap_iv);
@@ -529,18 +491,18 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
&wrapped_item, NULL) != SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_wrapping_key;
+ goto err_wrapping_key;
}
if (SECITEM_AllocItem (NULL, &wrapped_item, wrapped_item.len) == NULL)
{
res = CKR_HOST_MEMORY;
- goto end_wrapping_key;
+ goto err_wrapping_key;
}
if (PK11_WrapPrivKey(slot, wrapping_key, key->key, CKM_AES_CBC_PAD, &iv_item,
&wrapped_item, NULL) != SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_wrapped_item;
+ goto err_wrapped_item;
}
ctx = PK11_CreateContextBySymKey (CKM_AES_CBC_PAD, CKA_DECRYPT, wrapping_key,
@@ -548,32 +510,32 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
if (ctx == NULL)
{
res = CKR_GENERAL_ERROR;
- goto end_wrapped_item;
+ goto err_wrapped_item;
}
- memset (&der_info, 0, sizeof (der_info));
- if (SECITEM_AllocItem (NULL, &der_info, wrapped_item.len) == NULL)
+ memset (der_info, 0, sizeof (*der_info));
+ if (SECITEM_AllocItem (NULL, der_info, wrapped_item.len) == NULL)
{
PK11_DestroyContext (ctx, PR_TRUE);
res = CKR_HOST_MEMORY;
- goto end_wrapped_item;
+ goto err_wrapped_item;
}
- if (PK11_CipherOp (ctx, der_info.data, &der_info_len, der_info.len,
+ if (PK11_CipherOp (ctx, der_info->data, &der_info_len, der_info->len,
wrapped_item.data, wrapped_item.len) != SECSuccess)
{
PK11_DestroyContext (ctx, PR_TRUE);
res = CKR_GENERAL_ERROR;
- goto end_der_info;
+ goto err_der_info;
}
/* C_DecryptFinal is only available through this function. "Nice.". */
- ss = PK11_DigestFinal (ctx, der_info.data + der_info_len,
- &der_info.len, der_info.len - der_info_len);
+ ss = PK11_DigestFinal (ctx, der_info->data + der_info_len,
+ &der_info->len, der_info->len - der_info_len);
PK11_DestroyContext (ctx, PR_TRUE);
if (ss != SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_der_info;
+ goto err_der_info;
}
- der_info.len += der_info_len;
+ der_info->len += der_info_len;
/* Ugly... the PLArenaPool type is from NSPR, but NSS implementation accesses
memory only initialized through NSS's PORT_* */
@@ -581,46 +543,115 @@ ncr_private_key_export (struct ncr_private_key *key, void *dest,
if (arena == NULL)
{
res = CKR_HOST_MEMORY;
- goto end_der_info;
+ goto err_der_info;
}
/* "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)
+ private_key_info_asn1_template, der_info)
!= SECSuccess)
{
res = CKR_GENERAL_ERROR;
- goto end_arena;
+ goto err_arena;
}
/* Should we validate the version and algorithm ID here? */
+ *der_key = der_output.private_key;
+ *arena_ptr = arena;
+
+ SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
+ PK11_FreeSymKey (wrapping_key);
+ PK11_FreeSlot (slot);
+
+ return CKR_OK;
+
+ err_arena:
+ PORT_FreeArena (arena, PR_TRUE);
+ err_der_info:
+ SECITEM_ZfreeItem (der_info, PR_FALSE);
+ err_wrapped_item:
+ SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
+ err_wrapping_key:
+ PK11_FreeSymKey (wrapping_key);
+ err_slot:
+ PK11_FreeSlot (slot);
+ return res;
+}
+
+/* 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,
+ _Bool sensitive, const void *der, size_t der_size,
+ const void *public_value, size_t public_value_size)
+{
+ SECItem der_key;
+ SECItem public;
+ 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 (der != NULL, CKR_ARGUMENTS_BAD);
+
+ der_key.data = (void *)der;
+ der_key.len = der_size;
+ public.data = (void *)public_value;
+ public.len = public_value_size;
+ return private_key_create (key, type, sensitive, &der_key, &public);
+}
+
+CK_RV
+ncr_private_key_set_sensitive (struct ncr_private_key *key)
+{
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (key != NULL, CKR_KEY_HANDLE_INVALID);
+ key->sensitive = true;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_private_key_export (struct ncr_private_key *key, void *dest,
+ size_t *dest_size_ptr)
+{
+ PRArenaPool *arena;
+ SECItem der_info, der_key;
+ CK_RV res;
+
+ g_return_val_if_fail (dest_size_ptr != NULL, CKR_ARGUMENTS_BAD);
+
+ res = private_key_export (key, &der_key, &arena, &der_info);
+ if (res != CKR_OK)
+ return res;
+
if (dest == NULL)
{
- *dest_size_ptr = der_output.private_key.len;
- return CKR_OK;
+ *dest_size_ptr = der_key.len;
+ res = CKR_OK;
+ goto end;
}
- if (*dest_size_ptr < der_output.private_key.len)
+ if (*dest_size_ptr < der_key.len)
{
- *dest_size_ptr = der_output.private_key.len;
- return CKR_BUFFER_TOO_SMALL;
+ *dest_size_ptr = der_key.len;
+ res = CKR_BUFFER_TOO_SMALL;
+ goto end;
}
- *dest_size_ptr = der_output.private_key.len;
+ *dest_size_ptr = der_key.len;
- memcpy (dest, der_output.private_key.data, der_output.private_key.len);
+ memcpy (dest, der_key.data, der_key.len);
res = CKR_OK;
- end_arena:
+ end:
PORT_FreeArena (arena, PR_TRUE);
- end_der_info:
SECITEM_ZfreeItem (&der_info, PR_FALSE);
- end_wrapped_item:
- SECITEM_ZfreeItem (&wrapped_item, PR_FALSE);
- end_wrapping_key:
- PK11_FreeSymKey (wrapping_key);
- end_slot:
- PK11_FreeSlot (slot);
return res;
}
@@ -658,6 +689,26 @@ static const SEC_ASN1Template rsa_public_key_asn1_template[] =
{ 0, 0, NULL, 0 }
};
+struct rsa_private_key
+{
+ SECItem version;
+ SECItem modulus, public_exponent, private_exponent, prime_1, prime_2;
+ SECItem exponent_1, exponent_2, coefficient;
+};
+
+static const SEC_ASN1Template rsa_private_key_asn1_template[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct rsa_private_key) },
+#define INT(X) \
+ { SEC_ASN1_INTEGER, offsetof (struct rsa_private_key, X), NULL, 0 }
+
+ INT (version),
+ INT (modulus), INT (public_exponent), INT (private_exponent), INT (prime_1),
+ INT (prime_2), INT (exponent_1), INT (exponent_2), INT (coefficient),
+#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,
@@ -775,27 +826,9 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive,
size_t exponent_2_size, const void *coefficient,
size_t coefficient_size)
{
- struct rsa_pub_key
- {
- SECItem version;
- SECItem modulus, public_exponent, private_exponent, prime_1, prime_2;
- SECItem exponent_1, exponent_2, coefficient;
- };
-
- 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 (version),
- INT (modulus), INT (public_exponent), INT (private_exponent),
- INT (prime_1), INT (prime_2), INT (exponent_1), INT (exponent_2),
- INT (coefficient),
-#undef INT
- { 0, 0, NULL, 0 }
- };
static const uint8_t zero; /* = 0; */
- struct rsa_pub_key der_input;
+ struct rsa_private_key der_input;
SECItem der_key;
CK_RV res;
@@ -826,7 +859,8 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive,
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_private_key_asn1_template) == NULL)
return CKR_HOST_MEMORY;
res = private_key_create (key, CKK_RSA, sensitive, &der_key,
@@ -836,6 +870,94 @@ ncr_private_key_create_rsa (struct ncr_private_key **key, _Bool sensitive,
return res;
}
+CK_RV
+ncr_private_key_export_rsa (struct ncr_private_key *key, void *modulus,
+ size_t *modulus_size_ptr, void *public_exponent,
+ size_t *public_exponent_size_ptr,
+ void *private_exponent,
+ size_t *private_exponent_size_ptr,
+ void *prime_1, size_t *prime_1_size_ptr,
+ void *prime_2, size_t *prime_2_size_ptr,
+ void *exponent_1, size_t *exponent_1_size_ptr,
+ void *exponent_2, size_t *exponent_2_size_ptr,
+ void *coefficient, size_t *coefficient_size_ptr)
+{
+ struct rsa_private_key der_output;
+ PRArenaPool *arena;
+ SECItem der_info, der_key;
+ CK_RV res;
+
+ /* This works in C because "INT" is expanded only at the point where ALL_INTS
+ is used. */
+#define ALL_INTS \
+ INT (modulus); \
+ INT (public_exponent); \
+ INT (private_exponent); \
+ INT (prime_1); \
+ INT (prime_2); \
+ INT (exponent_1); \
+ INT (exponent_2); \
+ INT (coefficient);
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+#define INT(X) g_return_val_if_fail (X##_size_ptr != NULL, CKR_ARGUMENTS_BAD)
+ ALL_INTS;
+#undef INT
+
+ res = private_key_export (key, &der_key, &arena, &der_info);
+ if (res != CKR_OK)
+ return res;
+
+ /* Setting type to siUnsignedInteger requests removal of leading zeroes. */
+ der_output.version.type = siUnsignedInteger;
+#define INT(X) der_output.X.type = siUnsignedInteger
+ ALL_INTS;
+#undef INT
+ if (SEC_QuickDERDecodeItem (arena, &der_output, rsa_private_key_asn1_template,
+ &der_key) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end;
+ }
+
+ if (modulus == NULL || public_exponent == NULL || private_exponent == NULL
+ || prime_1 == NULL || prime_2 == NULL || exponent_1 == NULL
+ || exponent_2 == NULL || coefficient == NULL)
+ {
+#define INT(X) *X##_size_ptr = der_output.X.len
+ ALL_INTS;
+#undef INT
+ res = CKR_OK;
+ goto end;
+ }
+ res = CKR_OK;
+#define INT(X) \
+ do \
+ { \
+ if (*X##_size_ptr < der_output.X.len) \
+ res = CKR_BUFFER_TOO_SMALL; \
+ *X##_size_ptr = der_output.X.len; \
+ } \
+ while (0)
+ ALL_INTS;
+#undef INT
+ if (res != CKR_OK)
+ goto end;
+
+#define INT(X) memcpy((X), der_output.X.data, der_output.X.len)
+ ALL_INTS;
+#undef INT
+
+ end:
+ PORT_FreeArena (arena, PR_TRUE);
+ SECITEM_ZfreeItem (&der_info, PR_FALSE);
+ return res;
+#undef DO_INTS
+}
+
/* Asymmetric operations */
CK_RV