Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: content/child/webcrypto/platform_crypto_nss.cc

Issue 287133004: [webcrypto] Add JWK import/export of RSA private keys (NSS). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix comment typeo Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/child/webcrypto/platform_crypto.h ('k') | content/child/webcrypto/platform_crypto_openssl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/child/webcrypto/platform_crypto_nss.cc
diff --git a/content/child/webcrypto/platform_crypto_nss.cc b/content/child/webcrypto/platform_crypto_nss.cc
index eebd9e071b445b39baec6ae805a7f52d6456405e..a9b4c550f97b18a04060d976c39091d9279a04e7 100644
--- a/content/child/webcrypto/platform_crypto_nss.cc
+++ b/content/child/webcrypto/platform_crypto_nss.cc
@@ -596,10 +596,6 @@ void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) {
out->assign(item.data, item.data + item.len);
}
-// The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
-// function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
-// provide a fallback implementation.
-#if defined(USE_NSS)
// From PKCS#1 [http://tools.ietf.org/html/rfc3447]:
//
// RSAPrivateKey ::= SEQUENCE {
@@ -629,6 +625,10 @@ struct RSAPrivateKey {
SECItem coefficient;
};
+// The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
+// function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
+// provide a fallback implementation.
+#if defined(USE_NSS)
const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
{SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)},
{SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)},
@@ -641,6 +641,7 @@ const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
{SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)},
{SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)},
{0}};
+#endif // defined(USE_NSS)
// On success |value| will be filled with data which must be freed by
// SECITEM_FreeItem(value, PR_FALSE);
@@ -709,7 +710,6 @@ struct FreeRsaPrivateKey {
SECITEM_FreeItem(&out->coefficient, PR_FALSE);
}
};
-#endif // defined(USE_NSS)
} // namespace
@@ -968,6 +968,37 @@ Status ExportRsaPublicKey(PublicKey* key,
return Status::Success();
}
+void AssignVectorFromSecItem(const SECItem& item, std::vector<uint8>* output) {
+ output->assign(item.data, item.data + item.len);
+}
+
+Status ExportRsaPrivateKey(PrivateKey* key,
+ std::vector<uint8>* modulus,
+ std::vector<uint8>* public_exponent,
+ std::vector<uint8>* private_exponent,
+ std::vector<uint8>* prime1,
+ std::vector<uint8>* prime2,
+ std::vector<uint8>* exponent1,
+ std::vector<uint8>* exponent2,
+ std::vector<uint8>* coefficient) {
+ RSAPrivateKey key_props = {};
+ scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(&key_props);
+
+ if (!InitRSAPrivateKey(key->key(), &key_props))
+ return Status::OperationError();
+
+ AssignVectorFromSecItem(key_props.modulus, modulus);
+ AssignVectorFromSecItem(key_props.public_exponent, public_exponent);
+ AssignVectorFromSecItem(key_props.private_exponent, private_exponent);
+ AssignVectorFromSecItem(key_props.prime1, prime1);
+ AssignVectorFromSecItem(key_props.prime2, prime2);
+ AssignVectorFromSecItem(key_props.exponent1, exponent1);
+ AssignVectorFromSecItem(key_props.exponent2, exponent2);
+ AssignVectorFromSecItem(key_props.coefficient, coefficient);
+
+ return Status::Success();
+}
+
Status ExportKeyPkcs8(PrivateKey* key,
const blink::WebCryptoKeyAlgorithm& key_algorithm,
std::vector<uint8>* buffer) {
@@ -1494,6 +1525,111 @@ Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
return Status::Success();
}
+struct DestroyGenericObject {
+ void operator()(PK11GenericObject* o) const {
+ if (o)
+ PK11_DestroyGenericObject(o);
+ }
+};
+
+typedef scoped_ptr<PK11GenericObject, DestroyGenericObject>
+ ScopedPK11GenericObject;
+
+// Helper to add an attribute to a template.
+void AddAttribute(CK_ATTRIBUTE_TYPE type,
+ void* value,
+ unsigned long length,
+ std::vector<CK_ATTRIBUTE>* templ) {
+ CK_ATTRIBUTE attribute = {type, value, length};
+ templ->push_back(attribute);
+}
+
+// Helper to optionally add an attribute to a template, if the provided data is
+// non-empty.
+void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type,
+ const CryptoData& data,
+ std::vector<CK_ATTRIBUTE>* templ) {
+ if (!data.byte_length())
+ return;
+ CK_ATTRIBUTE attribute = {type, const_cast<unsigned char*>(data.bytes()),
+ data.byte_length()};
+ templ->push_back(attribute);
+}
+
+Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ const CryptoData& modulus,
+ const CryptoData& public_exponent,
+ const CryptoData& private_exponent,
+ const CryptoData& prime1,
+ const CryptoData& prime2,
+ const CryptoData& exponent1,
+ const CryptoData& exponent2,
+ const CryptoData& coefficient,
+ blink::WebCryptoKey* key) {
+ CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+ CK_BBOOL ck_false = CK_FALSE;
+
+ std::vector<CK_ATTRIBUTE> key_template;
+
+ AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template);
+ AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template);
+ AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template);
+ AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template);
+ AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template);
+
+ // Required properties.
+ AddOptionalAttribute(CKA_MODULUS, modulus, &key_template);
+ AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template);
+ AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template);
+
+ // Optional properties (all of these will have been specified or none).
+ AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template);
+ AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template);
+ AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template);
+ AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template);
+ AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template);
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+
+ ScopedPK11GenericObject key_object(PK11_CreateGenericObject(
+ slot.get(), &key_template[0], key_template.size(), PR_FALSE));
+
+ if (!key_object)
+ return Status::OperationError();
+
+ // The ID isn't guaranteed to be set by PKCS#11. However it is by softtoken so
+ // this should work.
+ SECItem object_id = {};
+ if (PK11_ReadRawAttribute(
+ PK11_TypeGeneric, key_object.get(), CKA_ID, &object_id) != SECSuccess)
+ return Status::OperationError();
+
+ crypto::ScopedSECKEYPrivateKey private_key(
+ PK11_FindKeyByKeyID(slot.get(), &object_id, NULL));
+ if (!private_key)
+ return Status::OperationError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm))
+ return Status::ErrorUnexpected();
+
+ scoped_ptr<PrivateKey> key_handle;
+ Status status =
+ PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle);
+ if (status.IsError())
+ return status;
+
+ *key = blink::WebCryptoKey::create(key_handle.release(),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ key_algorithm,
+ usage_mask);
+ return Status::Success();
+}
+
Status WrapSymKeyAesKw(SymKey* key,
SymKey* wrapping_key,
std::vector<uint8>* buffer) {
« no previous file with comments | « content/child/webcrypto/platform_crypto.h ('k') | content/child/webcrypto/platform_crypto_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698