| 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/evp.h> |
| 7 | 7 |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/numerics/safe_math.h" | 10 #include "base/numerics/safe_math.h" |
| 11 #include "base/stl_util.h" | |
| 12 #include "components/webcrypto/algorithms/aes.h" | 11 #include "components/webcrypto/algorithms/aes.h" |
| 13 #include "components/webcrypto/algorithms/util.h" | 12 #include "components/webcrypto/algorithms/util.h" |
| 14 #include "components/webcrypto/blink_key_handle.h" | 13 #include "components/webcrypto/blink_key_handle.h" |
| 15 #include "components/webcrypto/crypto_data.h" | 14 #include "components/webcrypto/crypto_data.h" |
| 16 #include "components/webcrypto/status.h" | 15 #include "components/webcrypto/status.h" |
| 17 #include "crypto/openssl_util.h" | 16 #include "crypto/openssl_util.h" |
| 18 #include "crypto/scoped_openssl_types.h" | 17 #include "crypto/scoped_openssl_types.h" |
| 19 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 20 | 19 |
| 21 namespace webcrypto { | 20 namespace webcrypto { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 } | 96 } |
| 98 | 97 |
| 99 // Otherwise make a copy of the counter and zero out the topmost bits so | 98 // Otherwise make a copy of the counter and zero out the topmost bits so |
| 100 // BN_bin2bn() can be called with a byte stream. | 99 // BN_bin2bn() can be called with a byte stream. |
| 101 unsigned int byte_length = CeilDiv(counter_length_bits, 8u); | 100 unsigned int byte_length = CeilDiv(counter_length_bits, 8u); |
| 102 std::vector<uint8_t> counter( | 101 std::vector<uint8_t> counter( |
| 103 counter_block.bytes() + counter_block.byte_length() - byte_length, | 102 counter_block.bytes() + counter_block.byte_length() - byte_length, |
| 104 counter_block.bytes() + counter_block.byte_length()); | 103 counter_block.bytes() + counter_block.byte_length()); |
| 105 counter[0] &= ~(0xFF << counter_length_remainder_bits); | 104 counter[0] &= ~(0xFF << counter_length_remainder_bits); |
| 106 | 105 |
| 107 return crypto::ScopedBIGNUM( | 106 return crypto::ScopedBIGNUM(BN_bin2bn(counter.data(), counter.size(), NULL)); |
| 108 BN_bin2bn(vector_as_array(&counter), counter.size(), NULL)); | |
| 109 } | 107 } |
| 110 | 108 |
| 111 // 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. |
| 112 std::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block, | 110 std::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block, |
| 113 unsigned int counter_length_bits) { | 111 unsigned int counter_length_bits) { |
| 114 unsigned int counter_length_bytes = counter_length_bits / 8; | 112 unsigned int counter_length_bytes = counter_length_bits / 8; |
| 115 unsigned int counter_length_bits_remainder = counter_length_bits % 8; | 113 unsigned int counter_length_bits_remainder = counter_length_bits % 8; |
| 116 | 114 |
| 117 std::vector<uint8_t> new_counter_block( | 115 std::vector<uint8_t> new_counter_block( |
| 118 counter_block.bytes(), | 116 counter_block.bytes(), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 | 197 |
| 200 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(), |
| 201 current_counter.get())) { | 199 current_counter.get())) { |
| 202 return Status::ErrorUnexpected(); | 200 return Status::ErrorUnexpected(); |
| 203 } | 201 } |
| 204 | 202 |
| 205 // If the counter can be incremented for the entire input without | 203 // If the counter can be incremented for the entire input without |
| 206 // wrapping-around, do it as a single call into BoringSSL. | 204 // wrapping-around, do it as a single call into BoringSSL. |
| 207 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) { |
| 208 return AesCtrEncrypt128BitCounter(cipher, CryptoData(raw_key), data, | 206 return AesCtrEncrypt128BitCounter(cipher, CryptoData(raw_key), data, |
| 209 counter_block, vector_as_array(buffer)); | 207 counter_block, buffer->data()); |
| 210 } | 208 } |
| 211 | 209 |
| 212 // Otherwise the encryption needs to be done in 2 parts. The first part using | 210 // Otherwise the encryption needs to be done in 2 parts. The first part using |
| 213 // the current counter_block, and the next part resetting the counter portion | 211 // the current counter_block, and the next part resetting the counter portion |
| 214 // of the block to zero. | 212 // of the block to zero. |
| 215 | 213 |
| 216 // This is guaranteed to fit in an "unsigned int" because input size in bytes | 214 // This is guaranteed to fit in an "unsigned int" because input size in bytes |
| 217 // fits in an "unsigned int". | 215 // fits in an "unsigned int". |
| 218 BN_ULONG num_blocks_part1 = BN_get_word(num_blocks_until_reset.get()); | 216 BN_ULONG num_blocks_part1 = BN_get_word(num_blocks_until_reset.get()); |
| 219 BN_ULONG input_size_part1 = num_blocks_part1 * AES_BLOCK_SIZE; | 217 BN_ULONG input_size_part1 = num_blocks_part1 * AES_BLOCK_SIZE; |
| 220 DCHECK_LT(input_size_part1, data.byte_length()); | 218 DCHECK_LT(input_size_part1, data.byte_length()); |
| 221 | 219 |
| 222 // Encrypt the first part (before wrap-around). | 220 // Encrypt the first part (before wrap-around). |
| 223 Status status = AesCtrEncrypt128BitCounter( | 221 Status status = AesCtrEncrypt128BitCounter( |
| 224 cipher, CryptoData(raw_key), CryptoData(data.bytes(), input_size_part1), | 222 cipher, CryptoData(raw_key), CryptoData(data.bytes(), input_size_part1), |
| 225 counter_block, vector_as_array(buffer)); | 223 counter_block, buffer->data()); |
| 226 if (status.IsError()) | 224 if (status.IsError()) |
| 227 return status; | 225 return status; |
| 228 | 226 |
| 229 // Encrypt the second part (after wrap-around). | 227 // Encrypt the second part (after wrap-around). |
| 230 std::vector<uint8_t> counter_block_part2 = | 228 std::vector<uint8_t> counter_block_part2 = |
| 231 BlockWithZeroedCounter(counter_block, counter_length_bits); | 229 BlockWithZeroedCounter(counter_block, counter_length_bits); |
| 232 | 230 |
| 233 return AesCtrEncrypt128BitCounter( | 231 return AesCtrEncrypt128BitCounter( |
| 234 cipher, CryptoData(raw_key), | 232 cipher, CryptoData(raw_key), |
| 235 CryptoData(data.bytes() + input_size_part1, | 233 CryptoData(data.bytes() + input_size_part1, |
| 236 data.byte_length() - input_size_part1), | 234 data.byte_length() - input_size_part1), |
| 237 CryptoData(counter_block_part2), | 235 CryptoData(counter_block_part2), buffer->data() + input_size_part1); |
| 238 vector_as_array(buffer) + input_size_part1); | |
| 239 } | 236 } |
| 240 | 237 |
| 241 class AesCtrImplementation : public AesAlgorithm { | 238 class AesCtrImplementation : public AesAlgorithm { |
| 242 public: | 239 public: |
| 243 AesCtrImplementation() : AesAlgorithm("CTR") {} | 240 AesCtrImplementation() : AesAlgorithm("CTR") {} |
| 244 | 241 |
| 245 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 242 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 246 const blink::WebCryptoKey& key, | 243 const blink::WebCryptoKey& key, |
| 247 const CryptoData& data, | 244 const CryptoData& data, |
| 248 std::vector<uint8_t>* buffer) const override { | 245 std::vector<uint8_t>* buffer) const override { |
| 249 return AesCtrEncryptDecrypt(algorithm, key, data, buffer); | 246 return AesCtrEncryptDecrypt(algorithm, key, data, buffer); |
| 250 } | 247 } |
| 251 | 248 |
| 252 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 249 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 253 const blink::WebCryptoKey& key, | 250 const blink::WebCryptoKey& key, |
| 254 const CryptoData& data, | 251 const CryptoData& data, |
| 255 std::vector<uint8_t>* buffer) const override { | 252 std::vector<uint8_t>* buffer) const override { |
| 256 return AesCtrEncryptDecrypt(algorithm, key, data, buffer); | 253 return AesCtrEncryptDecrypt(algorithm, key, data, buffer); |
| 257 } | 254 } |
| 258 }; | 255 }; |
| 259 | 256 |
| 260 } // namespace | 257 } // namespace |
| 261 | 258 |
| 262 scoped_ptr<AlgorithmImplementation> CreateAesCtrImplementation() { | 259 scoped_ptr<AlgorithmImplementation> CreateAesCtrImplementation() { |
| 263 return make_scoped_ptr(new AesCtrImplementation); | 260 return make_scoped_ptr(new AesCtrImplementation); |
| 264 } | 261 } |
| 265 | 262 |
| 266 } // namespace webcrypto | 263 } // namespace webcrypto |
| OLD | NEW |