| 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 6a62cb8f88f047954913a3468fe20b2601af489e..82361fb44a2376a9dce68414103b9d4c5dc15f3d 100644
|
| --- a/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| +++ b/content/renderer/webcrypto/webcrypto_impl_nss.cc
|
| @@ -84,23 +84,17 @@ void ShrinkBuffer(WebKit::WebArrayBuffer* buffer, unsigned new_size) {
|
| *buffer = new_buffer;
|
| }
|
|
|
| -} // namespace
|
| -
|
| -void WebCryptoImpl::Init() {
|
| - crypto::EnsureNSSInit();
|
| -}
|
| -
|
| -bool WebCryptoImpl::EncryptInternal(
|
| +bool AesCbcEncryptDecrypt(
|
| + CK_ATTRIBUTE_TYPE operation,
|
| const WebKit::WebCryptoAlgorithm& algorithm,
|
| const WebKit::WebCryptoKey& key,
|
| const unsigned char* data,
|
| unsigned data_size,
|
| WebKit::WebArrayBuffer* buffer) {
|
| - if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc)
|
| - return false;
|
| -
|
| + DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id());
|
| DCHECK_EQ(algorithm.id(), key.algorithm().id());
|
| DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type());
|
| + DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
|
|
|
| SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
|
|
|
| @@ -118,7 +112,7 @@ bool WebCryptoImpl::EncryptInternal(
|
| return false;
|
|
|
| crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
|
| - CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get()));
|
| + CKM_AES_CBC_PAD, operation, sym_key->key(), param.get()));
|
|
|
| if (!context.get())
|
| return false;
|
| @@ -133,6 +127,16 @@ bool WebCryptoImpl::EncryptInternal(
|
| return false;
|
| }
|
|
|
| + // PK11_CipherOp does an invalid memory access when given empty decryption
|
| + // input, or input which is not a multiple of the block size. See also
|
| + // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
|
| + if (operation == CKA_DECRYPT &&
|
| + (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) {
|
| + return false;
|
| + }
|
| +
|
| + // TODO(eroman): Refine the output buffer size. It can be computed exactly for
|
| + // encryption, and can be smaller for decryption.
|
| unsigned output_max_len = data_size + AES_BLOCK_SIZE;
|
| CHECK_GT(output_max_len, data_size);
|
|
|
| @@ -162,6 +166,40 @@ bool WebCryptoImpl::EncryptInternal(
|
| return true;
|
| }
|
|
|
| +} // namespace
|
| +
|
| +void WebCryptoImpl::Init() {
|
| + crypto::EnsureNSSInit();
|
| +}
|
| +
|
| +bool WebCryptoImpl::EncryptInternal(
|
| + const WebKit::WebCryptoAlgorithm& algorithm,
|
| + const WebKit::WebCryptoKey& key,
|
| + const unsigned char* data,
|
| + unsigned data_size,
|
| + WebKit::WebArrayBuffer* buffer) {
|
| + if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
|
| + return AesCbcEncryptDecrypt(
|
| + CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +bool WebCryptoImpl::DecryptInternal(
|
| + const WebKit::WebCryptoAlgorithm& algorithm,
|
| + const WebKit::WebCryptoKey& key,
|
| + const unsigned char* data,
|
| + unsigned data_size,
|
| + WebKit::WebArrayBuffer* buffer) {
|
| + if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
|
| + return AesCbcEncryptDecrypt(
|
| + CKA_DECRYPT, algorithm, key, data, data_size, buffer);
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| bool WebCryptoImpl::DigestInternal(
|
| const WebKit::WebCryptoAlgorithm& algorithm,
|
| const unsigned char* data,
|
|
|