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 23e446bdff7052d5174de891a46e552da145f541..366f9daf88862ff147cc167411f353e61a2b7b73 100644 |
--- a/content/renderer/webcrypto/webcrypto_impl_nss.cc |
+++ b/content/renderer/webcrypto/webcrypto_impl_nss.cc |
@@ -239,6 +239,11 @@ bool BigIntegerToLong(const uint8* data, |
return true; |
} |
+typedef scoped_ptr_malloc< |
Ryan Sleevi
2013/11/21 01:41:34
scoped_ptr_malloc is DEPRECATED, as scoped_ptr sup
padolph
2013/11/21 03:38:13
This typedef is no longer needed because of the ch
|
+ PRArenaPool, crypto::NSSDestroyer1<PRArenaPool, |
+ PORT_FreeArena, |
+ PR_FALSE> > ScopedPRArenaPool; |
+ |
} // namespace |
void WebCryptoImpl::Init() { |
@@ -649,4 +654,70 @@ bool WebCryptoImpl::VerifySignatureInternal( |
return true; |
} |
+bool WebCryptoImpl::ImportRsaPublicKeyInternal( |
eroman
2013/11/20 23:37:12
@rsleevi, dark lord of NSS: Can you review this fu
|
+ const unsigned char* modulus_data, |
+ unsigned modulus_size, |
+ const unsigned char* exponent_data, |
+ unsigned exponent_size, |
+ const blink::WebCryptoAlgorithm& algorithm, |
+ bool extractable, |
+ blink::WebCryptoKeyUsageMask usage_mask, |
+ blink::WebCryptoKey* key) { |
+ |
+ DCHECK(modulus_data); |
+ DCHECK(modulus_size); |
+ DCHECK(exponent_data); |
+ DCHECK(exponent_size); |
Ryan Sleevi
2013/11/21 01:41:34
Is Blink going to require these four fields be val
eroman
2013/11/21 01:55:41
The caller here is the JWK parsing code, which val
padolph
2013/11/21 03:38:13
Done.
|
+ |
+ // NSS does not provide a way to create an RSA public key directly from the |
+ // modulus and exponent values. But it can import an DER-encoded ASN.1 blob |
Ryan Sleevi
2013/11/21 01:41:34
"values. But" -> "values, but"
padolph
2013/11/21 03:38:13
Done.
|
+ // with the values and create the key from that. The code below follows the |
+ // recommendation described in |
+ // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7 |
+ |
+ ScopedPRArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
+ if (!arena.get()) |
+ return false; |
+ |
+ // Pack the input values into struct compatible with NSS ASN.1 encoding, and |
+ // set up the ASN.1 encoder template for it. |
+ struct RsaPublicKeyData { |
+ SECItem modulus; |
+ SECItem exponent; |
+ }; |
+ const RsaPublicKeyData pubkey_in = { |
+ {siUnsignedInteger, const_cast<unsigned char*>(modulus_data), |
+ modulus_size}, |
+ {siUnsignedInteger, const_cast<unsigned char*>(exponent_data), |
+ exponent_size}}; |
+ const SEC_ASN1Template RsaPublicKeyTemplate[] = { |
+ {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)}, |
+ {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), }, |
+ {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), }, |
+ {0, }}; |
Ryan Sleevi
2013/11/21 01:41:34
nit: I seem to recall that clang-format/the style
padolph
2013/11/21 03:38:13
The current format is what clang-format -style=Chr
|
+ |
+ // Do the ASN.1 encoding to produce the DER-formatted public key. In this |
+ // usage, SEC_ASN1EncodeItem() returns a pointer to the provided output |
+ // SECItem (pubkey_der) on success, or NULL on failure. |
Ryan Sleevi
2013/11/21 01:41:34
A subtle element of this is the fact that the SECI
padolph
2013/11/21 03:38:13
Done.
|
+ SECItem pubkey_der = {siBuffer, NULL, 0}; |
+ SECItem* const check_der_ptr = SEC_ASN1EncodeItem( |
+ arena.get(), &pubkey_der, &pubkey_in, RsaPublicKeyTemplate); |
+ if (!check_der_ptr) |
+ return false; |
+ DCHECK_EQ(&pubkey_der, check_der_ptr); |
+ |
+ // Import the DER to create an RSA SECKEYPublicKey. |
Ryan Sleevi
2013/11/21 01:41:34
nit: // Import the DER-encoded public key to...
padolph
2013/11/21 03:38:13
Done.
|
+ crypto::ScopedSECKEYPublicKey pubkey( |
+ SECKEY_ImportDERPublicKey(&pubkey_der, CKK_RSA)); |
+ if (!pubkey.get()) |
+ return false; |
+ |
+ *key = blink::WebCryptoKey::create(new PublicKeyHandle(pubkey.Pass()), |
+ blink::WebCryptoKeyTypePublic, |
+ extractable, |
+ algorithm, |
+ usage_mask); |
+ return true; |
+} |
+ |
} // namespace content |