diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-11-26 00:37:52 +0100 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-11-26 00:37:52 +0100 |
commit | 6185079fd24c308530a4cebc66acc86dd7b40375 (patch) | |
tree | 2e39ae53285f55bbf57050d0f24f95c8fbe5d0fa /lib | |
parent | eafbed071d3e3de75f8539c1473edd5a8af28cac (diff) | |
download | ncrypto-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.c | 312 |
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 |