Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: components/webcrypto/algorithms/aes_ctr.cc

Issue 2407633002: Use new BoringSSL scopers in //components. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/webcrypto/algorithms/aes_cbc.cc ('k') | components/webcrypto/algorithms/aes_gcm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « components/webcrypto/algorithms/aes_cbc.cc ('k') | components/webcrypto/algorithms/aes_gcm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698