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 |