Chromium Code Reviews| Index: components/webcrypto/algorithms/aes_kw.cc |
| diff --git a/components/webcrypto/algorithms/aes_kw.cc b/components/webcrypto/algorithms/aes_kw.cc |
| index 170def5201fff459799e4d33d350d9a283c44910..1820f57a627796db6a7a9b81f13ded57791ca02e 100644 |
| --- a/components/webcrypto/algorithms/aes_kw.cc |
| +++ b/components/webcrypto/algorithms/aes_kw.cc |
| @@ -2,63 +2,23 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include <openssl/evp.h> |
| +#include <openssl/aes.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <vector> |
| -#include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/numerics/safe_math.h" |
| -#include "base/stl_util.h" |
| #include "components/webcrypto/algorithms/aes.h" |
| -#include "components/webcrypto/algorithms/util.h" |
| #include "components/webcrypto/blink_key_handle.h" |
| #include "components/webcrypto/crypto_data.h" |
| #include "components/webcrypto/status.h" |
| -#include "crypto/openssl_util.h" |
| -#include "crypto/scoped_openssl_types.h" |
| namespace webcrypto { |
| namespace { |
| -const EVP_AEAD* GetAesKwAlgorithmFromKeySize(size_t key_size_bytes) { |
| - switch (key_size_bytes) { |
| - case 16: |
| - return EVP_aead_aes_128_key_wrap(); |
| - case 32: |
| - return EVP_aead_aes_256_key_wrap(); |
| - default: |
| - return NULL; |
| - } |
| -} |
| - |
| -Status AesKwEncryptDecrypt(EncryptOrDecrypt mode, |
| - const blink::WebCryptoAlgorithm& algorithm, |
| - const blink::WebCryptoKey& key, |
| - const CryptoData& data, |
| - std::vector<uint8_t>* buffer) { |
| - // These length checks are done in order to give a more specific error. These |
| - // are not required for correctness. |
| - if ((mode == ENCRYPT && data.byte_length() < 16) || |
| - (mode == DECRYPT && data.byte_length() < 24)) { |
| - return Status::ErrorDataTooSmall(); |
| - } |
| - if (data.byte_length() % 8) |
| - return Status::ErrorInvalidAesKwDataLength(); |
| - |
| - const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); |
| - |
| - return AeadEncryptDecrypt(mode, raw_key, data, |
| - 8, // tag_length_bytes |
| - CryptoData(), // iv |
| - CryptoData(), // additional_data |
| - GetAesKwAlgorithmFromKeySize(raw_key.size()), |
| - buffer); |
| -} |
| - |
| class AesKwImplementation : public AesAlgorithm { |
| public: |
| AesKwImplementation() |
| @@ -70,14 +30,68 @@ class AesKwImplementation : public AesAlgorithm { |
| const blink::WebCryptoKey& key, |
| const CryptoData& data, |
| std::vector<uint8_t>* buffer) const override { |
| - return AesKwEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer); |
| + // These length checks are done in order to give a more specific |
|
eroman
2016/10/10 20:27:59
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE
davidben
2016/10/10 23:49:54
Done. aes.h actually does not touch the error queu
|
| + // error. These are not required for correctness. |
| + if (data.byte_length() < 16) |
| + return Status::ErrorDataTooSmall(); |
| + if (data.byte_length() % 8) |
| + return Status::ErrorInvalidAesKwDataLength(); |
| + |
| + const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); |
| + if (raw_key.size() != 16 && raw_key.size() != 32) |
|
eroman
2016/10/10 20:27:59
Can you remove this check? (key import enforces th
davidben
2016/10/10 23:49:54
Done.
|
| + return Status::ErrorUnexpected(); |
| + AES_KEY aes_key; |
| + if (AES_set_encrypt_key(raw_key.data(), |
| + static_cast<unsigned>(raw_key.size() * 8), |
| + &aes_key) < 0) { |
| + return Status::OperationError(); |
| + } |
| + |
| + // Key wrap's overhead is 8 bytes. |
| + base::CheckedNumeric<size_t> length(data.byte_length()); |
|
eroman
2016/10/10 20:27:59
Should this be an |int| instead ? Although the API
davidben
2016/10/10 23:49:54
Well, it's also more fundamentally constrained by
|
| + length += 8; |
| + if (!length.IsValid()) |
| + return Status::ErrorDataTooLarge(); |
| + |
| + buffer->resize(length.ValueOrDie()); |
| + if (AES_wrap_key(&aes_key, nullptr /* default IV */, buffer->data(), |
| + data.bytes(), data.byte_length()) < 0) { |
| + return Status::OperationError(); |
| + } |
| + |
| + return Status::Success(); |
| } |
| Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
| const blink::WebCryptoKey& key, |
| const CryptoData& data, |
| std::vector<uint8_t>* buffer) const override { |
| - return AesKwEncryptDecrypt(DECRYPT, algorithm, key, data, buffer); |
| + // These length checks are done in order to give a more specific |
|
eroman
2016/10/10 20:27:59
crypto::OpenSSLErrStackTracer ?
davidben
2016/10/10 23:49:54
Done.
|
| + // error. These are not required for correctness. |
| + if (data.byte_length() < 24) |
| + return Status::ErrorDataTooSmall(); |
| + if (data.byte_length() % 8) |
| + return Status::ErrorInvalidAesKwDataLength(); |
| + |
| + const std::vector<uint8_t>& raw_key = GetSymmetricKeyData(key); |
| + if (raw_key.size() != 16 && raw_key.size() != 32) |
|
eroman
2016/10/10 20:27:59
Same comment as above -- we can forego this check
davidben
2016/10/10 23:49:54
Done.
|
| + return Status::ErrorUnexpected(); |
| + AES_KEY aes_key; |
| + if (AES_set_decrypt_key(raw_key.data(), |
| + static_cast<unsigned>(raw_key.size() * 8), |
| + &aes_key) < 0) { |
| + return Status::OperationError(); |
| + } |
| + |
| + // Key wrap's overhead is 8 bytes. |
| + buffer->resize(data.byte_length() - 8); |
| + |
| + if (AES_unwrap_key(&aes_key, nullptr /* default IV */, buffer->data(), |
| + data.bytes(), data.byte_length()) < 0) { |
| + return Status::OperationError(); |
| + } |
| + |
| + return Status::Success(); |
| } |
| }; |