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

Side by Side Diff: components/webcrypto/webcrypto_util.cc

Issue 1355873002: [refactor] More post-NSS WebCrypto cleanups (utility functions). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address David's comments Created 5 years, 3 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/webcrypto_util.h ('k') | no next file » | 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 "components/webcrypto/webcrypto_util.h" 5 #include "components/webcrypto/webcrypto_util.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/numerics/safe_math.h"
9 #include "components/webcrypto/status.h" 8 #include "components/webcrypto/status.h"
10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
11 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 10 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
12 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 11 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
13 12
14 namespace webcrypto { 13 namespace webcrypto {
15 14
16 namespace { 15 namespace {
17 16
18 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, 17 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
19 // to unsigned int. 18 // to unsigned int.
20 bool BigIntegerToUint(const uint8_t* data, 19 bool BigIntegerToUint(const uint8_t* data,
21 size_t data_size, 20 size_t data_size,
22 unsigned int* result) { 21 unsigned int* result) {
23 if (data_size == 0) 22 if (data_size == 0)
24 return false; 23 return false;
25 24
26 *result = 0; 25 *result = 0;
27 for (size_t i = 0; i < data_size; ++i) { 26 for (size_t i = 0; i < data_size; ++i) {
28 size_t reverse_i = data_size - i - 1; 27 size_t reverse_i = data_size - i - 1;
29 28
30 if (reverse_i >= sizeof(*result) && data[i]) 29 if (reverse_i >= sizeof(*result) && data[i])
31 return false; // Too large for a uint. 30 return false; // Too large for a uint.
32 31
33 *result |= data[i] << 8 * reverse_i; 32 *result |= data[i] << 8 * reverse_i;
34 } 33 }
35 return true; 34 return true;
36 } 35 }
37 36
38 Status GetShaBlockSizeBits(const blink::WebCryptoAlgorithm& algorithm,
39 unsigned int* block_size_bits) {
40 switch (algorithm.id()) {
41 case blink::WebCryptoAlgorithmIdSha1:
42 case blink::WebCryptoAlgorithmIdSha256:
43 *block_size_bits = 512;
44 return Status::Success();
45 case blink::WebCryptoAlgorithmIdSha384:
46 case blink::WebCryptoAlgorithmIdSha512:
47 *block_size_bits = 1024;
48 return Status::Success();
49 default:
50 return Status::ErrorUnsupported();
51 }
52 }
53 37
54 } // namespace 38 } // namespace
55 39
56 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { 40 blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
57 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); 41 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
58 } 42 }
59 43
60 blink::WebCryptoAlgorithm CreateHmacImportAlgorithm(
61 blink::WebCryptoAlgorithmId hash_id,
62 unsigned int length_bits) {
63 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
64 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
65 blink::WebCryptoAlgorithmIdHmac,
66 new blink::WebCryptoHmacImportParams(CreateAlgorithm(hash_id), true,
67 length_bits));
68 }
69
70 blink::WebCryptoAlgorithm CreateHmacImportAlgorithmNoLength(
71 blink::WebCryptoAlgorithmId hash_id) {
72 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
73 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
74 blink::WebCryptoAlgorithmIdHmac,
75 new blink::WebCryptoHmacImportParams(CreateAlgorithm(hash_id), false, 0));
76 }
77
78 blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm( 44 blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
79 blink::WebCryptoAlgorithmId id, 45 blink::WebCryptoAlgorithmId id,
80 blink::WebCryptoAlgorithmId hash_id) { 46 blink::WebCryptoAlgorithmId hash_id) {
81 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id)); 47 DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
82 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 48 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
83 id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id))); 49 id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
84 } 50 }
85 51
86 blink::WebCryptoAlgorithm CreateEcImportAlgorithm( 52 blink::WebCryptoAlgorithm CreateEcImportAlgorithm(
87 blink::WebCryptoAlgorithmId id, 53 blink::WebCryptoAlgorithmId id,
88 blink::WebCryptoNamedCurve named_curve) { 54 blink::WebCryptoNamedCurve named_curve) {
89 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 55 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
90 id, new blink::WebCryptoEcKeyImportParams(named_curve)); 56 id, new blink::WebCryptoEcKeyImportParams(named_curve));
91 } 57 }
92 58
93 bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a, 59 bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
94 blink::WebCryptoKeyUsageMask b) { 60 blink::WebCryptoKeyUsageMask b) {
95 return (a & b) == b; 61 return (a & b) == b;
96 } 62 }
97 63
98 // The WebCrypto spec defines the default value for the tag length, as well as
99 // the allowed values for tag length.
100 Status GetAesGcmTagLengthInBits(const blink::WebCryptoAesGcmParams* params,
101 unsigned int* tag_length_bits) {
102 *tag_length_bits = 128;
103 if (params->hasTagLengthBits())
104 *tag_length_bits = params->optionalTagLengthBits();
105
106 if (*tag_length_bits != 32 && *tag_length_bits != 64 &&
107 *tag_length_bits != 96 && *tag_length_bits != 104 &&
108 *tag_length_bits != 112 && *tag_length_bits != 120 &&
109 *tag_length_bits != 128)
110 return Status::ErrorInvalidAesGcmTagLength();
111
112 return Status::Success();
113 }
114
115 Status GetAesKeyGenLengthInBits(const blink::WebCryptoAesKeyGenParams* params,
116 unsigned int* keylen_bits) {
117 *keylen_bits = params->lengthBits();
118
119 if (*keylen_bits == 128 || *keylen_bits == 256)
120 return Status::Success();
121
122 // BoringSSL does not support 192-bit AES.
123 if (*keylen_bits == 192)
124 return Status::ErrorAes192BitUnsupported();
125
126 return Status::ErrorGenerateAesKeyLength();
127 }
128
129 Status GetHmacKeyGenLengthInBits(const blink::WebCryptoHmacKeyGenParams* params,
130 unsigned int* keylen_bits) {
131 if (!params->hasLengthBits())
132 return GetShaBlockSizeBits(params->hash(), keylen_bits);
133
134 *keylen_bits = params->optionalLengthBits();
135
136 // Zero-length HMAC keys are disallowed by the spec.
137 if (*keylen_bits == 0)
138 return Status::ErrorGenerateHmacKeyLengthZero();
139
140 return Status::Success();
141 }
142
143 Status GetHmacImportKeyLengthBits(
144 const blink::WebCryptoHmacImportParams* params,
145 unsigned int key_data_byte_length,
146 unsigned int* keylen_bits) {
147 if (key_data_byte_length == 0)
148 return Status::ErrorHmacImportEmptyKey();
149
150 // Make sure that the key data's length can be represented in bits without
151 // overflow.
152 base::CheckedNumeric<unsigned int> checked_keylen_bits(key_data_byte_length);
153 checked_keylen_bits *= 8;
154
155 if (!checked_keylen_bits.IsValid())
156 return Status::ErrorDataTooLarge();
157
158 unsigned int data_keylen_bits = checked_keylen_bits.ValueOrDie();
159
160 // Determine how many bits of the input to use.
161 *keylen_bits = data_keylen_bits;
162 if (params->hasLengthBits()) {
163 // The requested bit length must be:
164 // * No longer than the input data length
165 // * At most 7 bits shorter.
166 if (NumBitsToBytes(params->optionalLengthBits()) != key_data_byte_length)
167 return Status::ErrorHmacImportBadLength();
168 *keylen_bits = params->optionalLengthBits();
169 }
170
171 return Status::Success();
172 }
173
174 Status VerifyAesKeyLengthForImport(unsigned int keylen_bytes) {
175 if (keylen_bytes == 16 || keylen_bytes == 32)
176 return Status::Success();
177
178 // BoringSSL does not support 192-bit AES.
179 if (keylen_bytes == 24)
180 return Status::ErrorAes192BitUnsupported();
181
182 return Status::ErrorImportAesKeyLength();
183 }
184 64
185 Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages, 65 Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages,
186 blink::WebCryptoKeyUsageMask actual_usages, 66 blink::WebCryptoKeyUsageMask actual_usages,
187 bool allow_empty_usages) { 67 bool allow_empty_usages) {
188 if (!allow_empty_usages && actual_usages == 0) 68 if (!allow_empty_usages && actual_usages == 0)
189 return Status::ErrorCreateKeyEmptyUsages(); 69 return Status::ErrorCreateKeyEmptyUsages();
190 70
191 if (!ContainsKeyUsages(all_possible_usages, actual_usages)) 71 if (!ContainsKeyUsages(all_possible_usages, actual_usages))
192 return Status::ErrorCreateKeyBadUsages(); 72 return Status::ErrorCreateKeyBadUsages();
193 return Status::Success(); 73 return Status::Success();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 bytes->resize(length_bytes); 137 bytes->resize(length_bytes);
258 } 138 }
259 139
260 size_t remainder_bits = length_bits % 8; 140 size_t remainder_bits = length_bits % 8;
261 141
262 // Zero any "unused bits" in the final byte 142 // Zero any "unused bits" in the final byte
263 if (remainder_bits) 143 if (remainder_bits)
264 (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits); 144 (*bytes)[bytes->size() - 1] &= ~((0xFF) >> remainder_bits);
265 } 145 }
266 146
267 Status GetAesKeyLength(const blink::WebCryptoAlgorithm& key_length_algorithm,
268 bool* has_length_bits,
269 unsigned int* length_bits) {
270 const blink::WebCryptoAesDerivedKeyParams* params =
271 key_length_algorithm.aesDerivedKeyParams();
272
273 *has_length_bits = true;
274 *length_bits = params->lengthBits();
275
276 if (*length_bits == 128 || *length_bits == 256)
277 return Status::Success();
278
279 // BoringSSL does not support 192-bit AES.
280 if (*length_bits == 192)
281 return Status::ErrorAes192BitUnsupported();
282
283 return Status::ErrorGetAesKeyLength();
284 }
285
286 Status GetHmacKeyLength(const blink::WebCryptoAlgorithm& key_length_algorithm,
287 bool* has_length_bits,
288 unsigned int* length_bits) {
289 const blink::WebCryptoHmacImportParams* params =
290 key_length_algorithm.hmacImportParams();
291
292 if (params->hasLengthBits()) {
293 *has_length_bits = true;
294 *length_bits = params->optionalLengthBits();
295 if (*length_bits == 0)
296 return Status::ErrorGetHmacKeyLengthZero();
297 return Status::Success();
298 }
299
300 *has_length_bits = true;
301 return GetShaBlockSizeBits(params->hash(), length_bits);
302 }
303 147
304 Status GetUsagesForGenerateAsymmetricKey( 148 Status GetUsagesForGenerateAsymmetricKey(
305 blink::WebCryptoKeyUsageMask combined_usages, 149 blink::WebCryptoKeyUsageMask combined_usages,
306 blink::WebCryptoKeyUsageMask all_public_usages, 150 blink::WebCryptoKeyUsageMask all_public_usages,
307 blink::WebCryptoKeyUsageMask all_private_usages, 151 blink::WebCryptoKeyUsageMask all_private_usages,
308 blink::WebCryptoKeyUsageMask* public_usages, 152 blink::WebCryptoKeyUsageMask* public_usages,
309 blink::WebCryptoKeyUsageMask* private_usages) { 153 blink::WebCryptoKeyUsageMask* private_usages) {
310 Status status = CheckKeyCreationUsages(all_public_usages | all_private_usages, 154 Status status = CheckKeyCreationUsages(all_public_usages | all_private_usages,
311 combined_usages, true); 155 combined_usages, true);
312 if (status.IsError()) 156 if (status.IsError())
313 return status; 157 return status;
314 158
315 *public_usages = combined_usages & all_public_usages; 159 *public_usages = combined_usages & all_public_usages;
316 *private_usages = combined_usages & all_private_usages; 160 *private_usages = combined_usages & all_private_usages;
317 161
318 if (*private_usages == 0) 162 if (*private_usages == 0)
319 return Status::ErrorCreateKeyEmptyUsages(); 163 return Status::ErrorCreateKeyEmptyUsages();
320 164
321 return Status::Success(); 165 return Status::Success();
322 } 166 }
323 167
324 } // namespace webcrypto 168 } // namespace webcrypto
OLDNEW
« no previous file with comments | « components/webcrypto/webcrypto_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698