| 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) {
|
|
|