| Index: content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| diff --git a/content/renderer/webcrypto/webcrypto_impl_nss.cc b/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| index 7e966f16c5ee0f7a770ce51736bf4e6dc4049cde..c384dade4fe21775fd0d4deecc903b3979f85ce9 100644
|
| --- a/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| +++ b/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| @@ -324,12 +324,41 @@ bool ImportKeyInternalRaw(
|
| return true;
|
| }
|
|
|
| -typedef scoped_ptr_malloc<
|
| - CERTSubjectPublicKeyInfo,
|
| - crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
|
| - SECKEY_DestroySubjectPublicKeyInfo> >
|
| +typedef scoped_ptr<CERTSubjectPublicKeyInfo,
|
| + crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
|
| + SECKEY_DestroySubjectPublicKeyInfo> >
|
| ScopedCERTSubjectPublicKeyInfo;
|
|
|
| +// Validates an NSS KeyType against a WebCrypto algorithm. Some NSS KeyTypes
|
| +// contain enough information to fabricate a Web Crypto algorithm, which is
|
| +// returned if the input algorithm isNull(). This function indicates failure by
|
| +// returning a Null algorithm.
|
| +blink::WebCryptoAlgorithm ResolveNssKeyTypeWithInputAlgorithm(
|
| + KeyType key_type,
|
| + const blink::WebCryptoAlgorithm& algorithm_or_null) {
|
| + switch (key_type) {
|
| + case rsaKey:
|
| + // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and
|
| + // according to RFCs 4055/5756 this can be used for both encryption and
|
| + // signatures. However, this is not specific enough to build a compatible
|
| + // Web Crypto algorithm, since in Web Crypto, RSA encryption and signature
|
| + // algorithms are distinct. So if the input algorithm isNull() here, we
|
| + // have to fail.
|
| + if (!algorithm_or_null.isNull() && IsAlgorithmRsa(algorithm_or_null))
|
| + return algorithm_or_null;
|
| + break;
|
| + case dsaKey:
|
| + case ecKey:
|
| + case rsaPssKey:
|
| + case rsaOaepKey:
|
| + // TODO(padolph): Handle other key types.
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + return blink::WebCryptoAlgorithm::createNull();
|
| +}
|
| +
|
| bool ImportKeyInternalSpki(
|
| const unsigned char* key_data,
|
| unsigned key_data_size,
|
| @@ -342,16 +371,11 @@ bool ImportKeyInternalSpki(
|
|
|
| if (!key_data_size)
|
| return false;
|
| -
|
| DCHECK(key_data);
|
|
|
| // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
|
| // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
|
| - SECItem spki_item = {
|
| - siBuffer,
|
| - const_cast<uint8*>(key_data),
|
| - key_data_size
|
| - };
|
| + SECItem spki_item = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
|
| const ScopedCERTSubjectPublicKeyInfo spki(
|
| SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
|
| if (!spki)
|
| @@ -363,34 +387,10 @@ bool ImportKeyInternalSpki(
|
| return false;
|
|
|
| const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
|
| -
|
| - // Validate the sec_key_type against the input algorithm. Some NSS KeyType's
|
| - // contain enough information to fabricate a Web Crypto Algorithm, which will
|
| - // be used if the input algorithm isNull(). Others like 'rsaKey' do not (see
|
| - // below).
|
| blink::WebCryptoAlgorithm algorithm =
|
| - blink::WebCryptoAlgorithm::createNull();
|
| - switch (sec_key_type) {
|
| - case rsaKey:
|
| - // NSS's rsaKey KeyType maps to keys with SEC_OID_PKCS1_RSA_ENCRYPTION and
|
| - // according to RFC 4055 this can be used for both encryption and
|
| - // signatures. However, this is not specific enough to build a compatible
|
| - // Web Crypto algorithm, since in Web Crypto RSA encryption and signature
|
| - // algorithms are distinct. So if the input algorithm isNull() here, we
|
| - // have to fail.
|
| - if (algorithm_or_null.isNull() || !IsAlgorithmRsa(algorithm_or_null))
|
| - return false;
|
| - algorithm = algorithm_or_null;
|
| - break;
|
| - case dsaKey:
|
| - case ecKey:
|
| - case rsaPssKey:
|
| - case rsaOaepKey:
|
| - // TODO(padolph): Handle other key types.
|
| - return false;
|
| - default:
|
| - return false;
|
| - }
|
| + ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
|
| + if (algorithm.isNull())
|
| + return false;
|
|
|
| *key = blink::WebCryptoKey::create(
|
| new PublicKeyHandle(sec_public_key.Pass()),
|
| @@ -429,6 +429,56 @@ bool ExportKeyInternalSpki(
|
| return true;
|
| }
|
|
|
| +bool ImportKeyInternalPkcs8(
|
| + const unsigned char* key_data,
|
| + unsigned key_data_size,
|
| + const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| + bool extractable,
|
| + blink::WebCryptoKeyUsageMask usage_mask,
|
| + blink::WebCryptoKey* key) {
|
| +
|
| + DCHECK(key);
|
| +
|
| + if (!key_data_size)
|
| + return false;
|
| + DCHECK(key_data);
|
| +
|
| + // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
|
| + // private key info object.
|
| + SECItem pki_der = {siBuffer, const_cast<uint8*>(key_data), key_data_size};
|
| +
|
| + SECKEYPrivateKey* seckey_private_key = NULL;
|
| + if (PK11_ImportDERPrivateKeyInfoAndReturnKey(
|
| + PK11_GetInternalSlot(),
|
| + &pki_der,
|
| + NULL, // nickname
|
| + NULL, // publicValue
|
| + false, // isPerm
|
| + false, // isPrivate
|
| + KU_ALL, // usage
|
| + &seckey_private_key,
|
| + NULL) != SECSuccess) {
|
| + return false;
|
| + }
|
| + DCHECK(seckey_private_key);
|
| + crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
|
| +
|
| + const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
|
| + blink::WebCryptoAlgorithm algorithm =
|
| + ResolveNssKeyTypeWithInputAlgorithm(sec_key_type, algorithm_or_null);
|
| + if (algorithm.isNull())
|
| + return false;
|
| +
|
| + *key = blink::WebCryptoKey::create(
|
| + new PrivateKeyHandle(private_key.Pass()),
|
| + blink::WebCryptoKeyTypePrivate,
|
| + extractable,
|
| + algorithm,
|
| + usage_mask);
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| void WebCryptoImpl::Init() {
|
| @@ -680,9 +730,14 @@ bool WebCryptoImpl::ImportKeyInternal(
|
| usage_mask,
|
| key);
|
| case blink::WebCryptoKeyFormatPkcs8:
|
| - // TODO(padolph): Handle PKCS#8 private key import
|
| - return false;
|
| + return ImportKeyInternalPkcs8(key_data,
|
| + key_data_size,
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| default:
|
| + // NOTE: blink::WebCryptoKeyFormatJwk is handled one level above.
|
| return false;
|
| }
|
| }
|
|
|