| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <openssl/aes.h> | 5 #include <openssl/aes.h> |
| 6 #include <openssl/evp.h> | 6 #include <openssl/bn.h> |
| 7 #include <openssl/cipher.h> |
| 7 #include <stddef.h> | 8 #include <stddef.h> |
| 8 #include <stdint.h> | 9 #include <stdint.h> |
| 9 #include <string.h> | 10 #include <string.h> |
| 10 | 11 |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/numerics/safe_math.h" | 15 #include "base/numerics/safe_math.h" |
| 15 #include "components/webcrypto/algorithms/aes.h" | 16 #include "components/webcrypto/algorithms/aes.h" |
| 16 #include "components/webcrypto/algorithms/util.h" | 17 #include "components/webcrypto/algorithms/util.h" |
| 17 #include "components/webcrypto/blink_key_handle.h" | 18 #include "components/webcrypto/blink_key_handle.h" |
| 18 #include "components/webcrypto/crypto_data.h" | 19 #include "components/webcrypto/crypto_data.h" |
| 19 #include "components/webcrypto/status.h" | 20 #include "components/webcrypto/status.h" |
| 20 #include "crypto/openssl_util.h" | 21 #include "crypto/openssl_util.h" |
| 21 #include "crypto/scoped_openssl_types.h" | |
| 22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 23 | 23 |
| 24 namespace webcrypto { | 24 namespace webcrypto { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 const EVP_CIPHER* GetAESCipherByKeyLength(size_t key_length_bytes) { | 28 const EVP_CIPHER* GetAESCipherByKeyLength(size_t key_length_bytes) { |
| 29 // 192-bit AES is intentionally unsupported (http://crbug.com/533699). | 29 // 192-bit AES is intentionally unsupported (http://crbug.com/533699). |
| 30 switch (key_length_bytes) { | 30 switch (key_length_bytes) { |
| 31 case 16: | 31 case 16: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 43 // |input.byte_length()|. | 43 // |input.byte_length()|. |
| 44 Status AesCtrEncrypt128BitCounter(const EVP_CIPHER* cipher, | 44 Status AesCtrEncrypt128BitCounter(const EVP_CIPHER* cipher, |
| 45 const CryptoData& raw_key, | 45 const CryptoData& raw_key, |
| 46 const CryptoData& input, | 46 const CryptoData& input, |
| 47 const CryptoData& counter, | 47 const CryptoData& counter, |
| 48 uint8_t* output) { | 48 uint8_t* output) { |
| 49 DCHECK(cipher); | 49 DCHECK(cipher); |
| 50 DCHECK_EQ(16u, counter.byte_length()); | 50 DCHECK_EQ(16u, counter.byte_length()); |
| 51 | 51 |
| 52 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 52 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
| 53 crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> context( | 53 bssl::ScopedEVP_CIPHER_CTX context; |
| 54 EVP_CIPHER_CTX_new()); | |
| 55 | |
| 56 if (!context.get()) | |
| 57 return Status::OperationError(); | |
| 58 | |
| 59 if (!EVP_CipherInit_ex(context.get(), cipher, NULL, raw_key.bytes(), | 54 if (!EVP_CipherInit_ex(context.get(), cipher, NULL, raw_key.bytes(), |
| 60 counter.bytes(), ENCRYPT)) { | 55 counter.bytes(), ENCRYPT)) { |
| 61 return Status::OperationError(); | 56 return Status::OperationError(); |
| 62 } | 57 } |
| 63 | 58 |
| 64 int output_len = 0; | 59 int output_len = 0; |
| 65 if (!EVP_CipherUpdate(context.get(), output, &output_len, input.bytes(), | 60 if (!EVP_CipherUpdate(context.get(), output, &output_len, input.bytes(), |
| 66 input.byte_length())) { | 61 input.byte_length())) { |
| 67 return Status::OperationError(); | 62 return Status::OperationError(); |
| 68 } | 63 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 80 } | 75 } |
| 81 | 76 |
| 82 // Returns ceil(a/b), where a and b are integers. | 77 // Returns ceil(a/b), where a and b are integers. |
| 83 template <typename T> | 78 template <typename T> |
| 84 T CeilDiv(T a, T b) { | 79 T CeilDiv(T a, T b) { |
| 85 return a == 0 ? 0 : 1 + (a - 1) / b; | 80 return a == 0 ? 0 : 1 + (a - 1) / b; |
| 86 } | 81 } |
| 87 | 82 |
| 88 // Extracts the counter as a BIGNUM. The counter is the rightmost | 83 // Extracts the counter as a BIGNUM. The counter is the rightmost |
| 89 // "counter_length_bits" of the block, interpreted as a big-endian number. | 84 // "counter_length_bits" of the block, interpreted as a big-endian number. |
| 90 crypto::ScopedBIGNUM GetCounter(const CryptoData& counter_block, | 85 bssl::UniquePtr<BIGNUM> GetCounter(const CryptoData& counter_block, |
| 91 unsigned int counter_length_bits) { | 86 unsigned int counter_length_bits) { |
| 92 unsigned int counter_length_remainder_bits = (counter_length_bits % 8); | 87 unsigned int counter_length_remainder_bits = (counter_length_bits % 8); |
| 93 | 88 |
| 94 // If the counter is a multiple of 8 bits then can call BN_bin2bn() directly. | 89 // If the counter is a multiple of 8 bits then can call BN_bin2bn() directly. |
| 95 if (counter_length_remainder_bits == 0) { | 90 if (counter_length_remainder_bits == 0) { |
| 96 unsigned int byte_length = counter_length_bits / 8; | 91 unsigned int byte_length = counter_length_bits / 8; |
| 97 return crypto::ScopedBIGNUM(BN_bin2bn( | 92 return bssl::UniquePtr<BIGNUM>(BN_bin2bn( |
| 98 counter_block.bytes() + counter_block.byte_length() - byte_length, | 93 counter_block.bytes() + counter_block.byte_length() - byte_length, |
| 99 byte_length, NULL)); | 94 byte_length, NULL)); |
| 100 } | 95 } |
| 101 | 96 |
| 102 // Otherwise make a copy of the counter and zero out the topmost bits so | 97 // Otherwise make a copy of the counter and zero out the topmost bits so |
| 103 // BN_bin2bn() can be called with a byte stream. | 98 // BN_bin2bn() can be called with a byte stream. |
| 104 unsigned int byte_length = CeilDiv(counter_length_bits, 8u); | 99 unsigned int byte_length = CeilDiv(counter_length_bits, 8u); |
| 105 std::vector<uint8_t> counter( | 100 std::vector<uint8_t> counter( |
| 106 counter_block.bytes() + counter_block.byte_length() - byte_length, | 101 counter_block.bytes() + counter_block.byte_length() - byte_length, |
| 107 counter_block.bytes() + counter_block.byte_length()); | 102 counter_block.bytes() + counter_block.byte_length()); |
| 108 counter[0] &= ~(0xFF << counter_length_remainder_bits); | 103 counter[0] &= ~(0xFF << counter_length_remainder_bits); |
| 109 | 104 |
| 110 return crypto::ScopedBIGNUM(BN_bin2bn(counter.data(), counter.size(), NULL)); | 105 return bssl::UniquePtr<BIGNUM>( |
| 106 BN_bin2bn(counter.data(), counter.size(), NULL)); |
| 111 } | 107 } |
| 112 | 108 |
| 113 // Returns a counter block with the counter bits all set all zero. | 109 // Returns a counter block with the counter bits all set all zero. |
| 114 std::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block, | 110 std::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block, |
| 115 unsigned int counter_length_bits) { | 111 unsigned int counter_length_bits) { |
| 116 unsigned int counter_length_bytes = counter_length_bits / 8; | 112 unsigned int counter_length_bytes = counter_length_bits / 8; |
| 117 unsigned int counter_length_bits_remainder = counter_length_bits % 8; | 113 unsigned int counter_length_bits_remainder = counter_length_bits % 8; |
| 118 | 114 |
| 119 std::vector<uint8_t> new_counter_block( | 115 std::vector<uint8_t> new_counter_block( |
| 120 counter_block.bytes(), | 116 counter_block.bytes(), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 return Status::ErrorDataTooLarge(); | 162 return Status::ErrorDataTooLarge(); |
| 167 | 163 |
| 168 const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size()); | 164 const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size()); |
| 169 if (!cipher) | 165 if (!cipher) |
| 170 return Status::ErrorUnexpected(); | 166 return Status::ErrorUnexpected(); |
| 171 | 167 |
| 172 const CryptoData counter_block(params->counter()); | 168 const CryptoData counter_block(params->counter()); |
| 173 buffer->resize(output_max_len.ValueOrDie()); | 169 buffer->resize(output_max_len.ValueOrDie()); |
| 174 | 170 |
| 175 // The total number of possible counter values is pow(2, counter_length_bits) | 171 // The total number of possible counter values is pow(2, counter_length_bits) |
| 176 crypto::ScopedBIGNUM num_counter_values(BN_new()); | 172 bssl::UniquePtr<BIGNUM> num_counter_values(BN_new()); |
| 177 if (!BN_lshift(num_counter_values.get(), BN_value_one(), counter_length_bits)) | 173 if (!BN_lshift(num_counter_values.get(), BN_value_one(), counter_length_bits)) |
| 178 return Status::ErrorUnexpected(); | 174 return Status::ErrorUnexpected(); |
| 179 | 175 |
| 180 crypto::ScopedBIGNUM current_counter = | 176 bssl::UniquePtr<BIGNUM> current_counter = |
| 181 GetCounter(counter_block, counter_length_bits); | 177 GetCounter(counter_block, counter_length_bits); |
| 182 | 178 |
| 183 // The number of AES blocks needed for encryption/decryption. The counter is | 179 // The number of AES blocks needed for encryption/decryption. The counter is |
| 184 // incremented this many times. | 180 // incremented this many times. |
| 185 crypto::ScopedBIGNUM num_output_blocks(BN_new()); | 181 bssl::UniquePtr<BIGNUM> num_output_blocks(BN_new()); |
| 186 if (!BN_set_word( | 182 if (!BN_set_word( |
| 187 num_output_blocks.get(), | 183 num_output_blocks.get(), |
| 188 CeilDiv(buffer->size(), static_cast<size_t>(AES_BLOCK_SIZE)))) { | 184 CeilDiv(buffer->size(), static_cast<size_t>(AES_BLOCK_SIZE)))) { |
| 189 return Status::ErrorUnexpected(); | 185 return Status::ErrorUnexpected(); |
| 190 } | 186 } |
| 191 | 187 |
| 192 // If the counter is going to be incremented more times than there are counter | 188 // If the counter is going to be incremented more times than there are counter |
| 193 // values, fail. (Repeating values of the counter block is bad). | 189 // values, fail. (Repeating values of the counter block is bad). |
| 194 if (BN_cmp(num_output_blocks.get(), num_counter_values.get()) > 0) | 190 if (BN_cmp(num_output_blocks.get(), num_counter_values.get()) > 0) |
| 195 return Status::ErrorAesCtrInputTooLongCounterRepeated(); | 191 return Status::ErrorAesCtrInputTooLongCounterRepeated(); |
| 196 | 192 |
| 197 // This is the number of blocks that can be successfully encrypted without | 193 // This is the number of blocks that can be successfully encrypted without |
| 198 // overflowing the counter. Encrypting the subsequent block will need to | 194 // overflowing the counter. Encrypting the subsequent block will need to |
| 199 // reset the counter to zero. | 195 // reset the counter to zero. |
| 200 crypto::ScopedBIGNUM num_blocks_until_reset(BN_new()); | 196 bssl::UniquePtr<BIGNUM> num_blocks_until_reset(BN_new()); |
| 201 | 197 |
| 202 if (!BN_sub(num_blocks_until_reset.get(), num_counter_values.get(), | 198 if (!BN_sub(num_blocks_until_reset.get(), num_counter_values.get(), |
| 203 current_counter.get())) { | 199 current_counter.get())) { |
| 204 return Status::ErrorUnexpected(); | 200 return Status::ErrorUnexpected(); |
| 205 } | 201 } |
| 206 | 202 |
| 207 // If the counter can be incremented for the entire input without | 203 // If the counter can be incremented for the entire input without |
| 208 // wrapping-around, do it as a single call into BoringSSL. | 204 // wrapping-around, do it as a single call into BoringSSL. |
| 209 if (BN_cmp(num_blocks_until_reset.get(), num_output_blocks.get()) >= 0) { | 205 if (BN_cmp(num_blocks_until_reset.get(), num_output_blocks.get()) >= 0) { |
| 210 return AesCtrEncrypt128BitCounter(cipher, CryptoData(raw_key), data, | 206 return AesCtrEncrypt128BitCounter(cipher, CryptoData(raw_key), data, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 254 } |
| 259 }; | 255 }; |
| 260 | 256 |
| 261 } // namespace | 257 } // namespace |
| 262 | 258 |
| 263 std::unique_ptr<AlgorithmImplementation> CreateAesCtrImplementation() { | 259 std::unique_ptr<AlgorithmImplementation> CreateAesCtrImplementation() { |
| 264 return base::WrapUnique(new AesCtrImplementation); | 260 return base::WrapUnique(new AesCtrImplementation); |
| 265 } | 261 } |
| 266 | 262 |
| 267 } // namespace webcrypto | 263 } // namespace webcrypto |
| OLD | NEW |