Chromium Code Reviews| 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 a20f72fb6bfd1bfe4336cb9a60deb8f15e3bd3f0..9638134fa6545532387e4e17b51f13b07057179b 100644 |
| --- a/content/renderer/webcrypto/webcrypto_impl_nss.cc |
| +++ b/content/renderer/webcrypto/webcrypto_impl_nss.cc |
| @@ -24,10 +24,7 @@ namespace { |
| class SymKeyHandle : public WebKit::WebCryptoKeyHandle { |
| public: |
| - explicit SymKeyHandle(crypto::ScopedPK11SymKey key) { |
| - DCHECK(!key_.get()); |
| - key_ = key.Pass(); |
| - } |
| + explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} |
| PK11SymKey* key() { return key_.get(); } |
| @@ -37,6 +34,32 @@ class SymKeyHandle : public WebKit::WebCryptoKeyHandle { |
| DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); |
| }; |
| +class PublicKeyHandle : public WebKit::WebCryptoKeyHandle { |
| + public: |
| + explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) |
| + : key_(key.Pass()) {} |
| + |
| + SECKEYPublicKey* key() { return key_.get(); } |
| + |
| + private: |
| + crypto::ScopedSECKEYPublicKey key_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); |
| +}; |
| + |
| +class PrivateKeyHandle : public WebKit::WebCryptoKeyHandle { |
| + public: |
| + explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) |
| + : key_(key.Pass()) {} |
| + |
| + SECKEYPrivateKey* key() { return key_.get(); } |
| + |
| + private: |
| + crypto::ScopedSECKEYPrivateKey key_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); |
| +}; |
| + |
| HASH_HashType WebCryptoAlgorithmToNSSHashType( |
| const WebKit::WebCryptoAlgorithm& algorithm) { |
| switch (algorithm.id()) { |
| @@ -323,6 +346,101 @@ bool WebCryptoImpl::GenerateKeyInternal( |
| return true; |
| } |
| +bool WebCryptoImpl::GenerateKeyPairInternal( |
| + const WebKit::WebCryptoAlgorithm& algorithm, |
| + scoped_ptr<WebKit::WebCryptoKeyHandle>* public_key_handle, |
| + scoped_ptr<WebKit::WebCryptoKeyHandle>* private_key_handle) { |
| + |
| + // TODO(padolph) Handle other asymmetric algorithm key generation |
| + switch (algorithm.id()) { |
| + case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| + case WebKit::WebCryptoAlgorithmIdRsaOaep: |
| + case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
| + const WebKit::WebCryptoRsaKeyGenParams* const params = |
| + algorithm.rsaKeyGenParams(); |
| + DCHECK(params); |
| + |
| + crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
| + if (!slot || !params->modulusLength() || |
| + !params->publicExponent().size()) { |
|
eroman
2013/10/24 22:28:59
Sleevi: General question: In WebCrypto's "BigInteg
|
| + return false; |
| + } |
| + |
| + // The Web Crypto API says params->m_publicExponent is in big-endian |
| + // order: the first element in the vector is the most significant digit. |
| + // Leading zeros may or may not be present. |
| + |
| + // First offset past any leading zeros in publicExponent. |
|
eroman
2013/10/24 22:28:59
Could you please extract this block of code to a s
padolph
2013/10/25 01:21:46
Done.
|
| + size_t start_index; |
| + for (start_index = 0; start_index < params->publicExponent().size(); |
|
eroman
2013/10/24 22:28:59
In my opinion this logic would be more readable as
padolph
2013/10/25 01:21:46
Done.
|
| + ++start_index) { |
| + if (params->publicExponent()[start_index] != 0x0) |
| + break; |
| + } |
| + const size_t exponent_size = |
| + params->publicExponent().size() - start_index; |
| + if (start_index == params->publicExponent().size() || |
| + exponent_size > sizeof(unsigned long)) { |
| + return false; |
| + } |
| + |
| + // Then convert the remaining data to an unsigned long. |
| + const size_t end_index = params->publicExponent().size() - 1; |
| + unsigned long public_exponent = 0; |
| + for (int i = end_index; i >= static_cast<int>(start_index); --i) { |
| + public_exponent |= params->publicExponent()[i] << (8 * (end_index - i)); |
| + } |
| + |
| + PK11RSAGenParams param; |
| + param.keySizeInBits = params->modulusLength(); |
| + param.pe = public_exponent; |
| + |
| + // Flags are verified at the Blink layer; here the flags are set to all |
| + // possible operations for the given key type. |
| + CK_FLAGS operation_flags; |
| + switch (algorithm.id()) { |
| + case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| + operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; |
| + break; |
| + case WebKit::WebCryptoAlgorithmIdRsaOaep: |
| + operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; |
| + break; |
| + case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| + operation_flags = CKF_SIGN | CKF_VERIFY; |
| + break; |
| + default: |
| + NOTREACHED(); |
| + return false; |
| + } |
| + const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT | |
| + CKF_SIGN | CKF_VERIFY | CKF_WRAP | |
| + CKF_UNWRAP; |
| + const PK11AttrFlags attribute_flags = 0; // default all PK11_ATTR_ flags |
| + |
| + SECKEYPublicKey* sec_public_key; |
| + crypto::ScopedSECKEYPrivateKey private_key( |
| + PK11_GenerateKeyPairWithOpFlags(slot.get(), |
| + CKM_RSA_PKCS_KEY_PAIR_GEN, |
| + ¶m, |
| + &sec_public_key, |
| + attribute_flags, |
| + operation_flags, |
| + operation_flags_mask, |
| + NULL)); |
| + if (!private_key) { |
| + return false; |
| + } |
| + crypto::ScopedSECKEYPublicKey public_key(sec_public_key); |
| + |
| + public_key_handle->reset(new PublicKeyHandle(public_key.Pass())); |
| + private_key_handle->reset(new PrivateKeyHandle(private_key.Pass())); |
| + |
| + return true; |
| + } |
| + default: |
| + return false; |
| + } |
| +} |
| bool WebCryptoImpl::ImportKeyInternal( |
| WebKit::WebCryptoKeyFormat format, |