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/hmac.h> | 5 #include <openssl/hmac.h> |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/numerics/safe_math.h" | |
8 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
9 #include "components/webcrypto/algorithm_implementation.h" | 10 #include "components/webcrypto/algorithm_implementation.h" |
11 #include "components/webcrypto/algorithms/secret_key_util.h" | |
10 #include "components/webcrypto/algorithms/util_openssl.h" | 12 #include "components/webcrypto/algorithms/util_openssl.h" |
11 #include "components/webcrypto/crypto_data.h" | 13 #include "components/webcrypto/crypto_data.h" |
12 #include "components/webcrypto/jwk.h" | 14 #include "components/webcrypto/jwk.h" |
13 #include "components/webcrypto/key.h" | 15 #include "components/webcrypto/key.h" |
14 #include "components/webcrypto/status.h" | 16 #include "components/webcrypto/status.h" |
15 #include "components/webcrypto/webcrypto_util.h" | 17 #include "components/webcrypto/webcrypto_util.h" |
16 #include "crypto/openssl_util.h" | 18 #include "crypto/openssl_util.h" |
17 #include "crypto/secure_util.h" | 19 #include "crypto/secure_util.h" |
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 20 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
19 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
20 | 22 |
21 namespace webcrypto { | 23 namespace webcrypto { |
22 | 24 |
23 namespace { | 25 namespace { |
24 | 26 |
27 Status GetShaBlockSizeBits(const blink::WebCryptoAlgorithm& algorithm, | |
28 unsigned int* block_size_bits) { | |
29 switch (algorithm.id()) { | |
30 case blink::WebCryptoAlgorithmIdSha1: | |
31 case blink::WebCryptoAlgorithmIdSha256: | |
32 *block_size_bits = 512; | |
33 return Status::Success(); | |
34 case blink::WebCryptoAlgorithmIdSha384: | |
35 case blink::WebCryptoAlgorithmIdSha512: | |
36 *block_size_bits = 1024; | |
davidben
2015/09/18 22:15:59
Probably for later, but OpenSSL knows this already
eroman
2015/09/18 23:13:23
Thanks, I will look at that in a follow-up!
For no
| |
37 return Status::Success(); | |
38 default: | |
39 return Status::ErrorUnsupported(); | |
40 } | |
41 } | |
42 | |
43 // Gets the requested key length in bits for an HMAC import operation. | |
44 Status GetHmacImportKeyLengthBits( | |
45 const blink::WebCryptoHmacImportParams* params, | |
46 unsigned int key_data_byte_length, | |
47 unsigned int* keylen_bits) { | |
48 if (key_data_byte_length == 0) | |
49 return Status::ErrorHmacImportEmptyKey(); | |
50 | |
51 // Make sure that the key data's length can be represented in bits without | |
52 // overflow. | |
53 base::CheckedNumeric<unsigned int> checked_keylen_bits(key_data_byte_length); | |
54 checked_keylen_bits *= 8; | |
55 | |
56 if (!checked_keylen_bits.IsValid()) | |
57 return Status::ErrorDataTooLarge(); | |
58 | |
59 unsigned int data_keylen_bits = checked_keylen_bits.ValueOrDie(); | |
60 | |
61 // Determine how many bits of the input to use. | |
62 *keylen_bits = data_keylen_bits; | |
63 if (params->hasLengthBits()) { | |
64 // The requested bit length must be: | |
65 // * No longer than the input data length | |
66 // * At most 7 bits shorter. | |
67 if (NumBitsToBytes(params->optionalLengthBits()) != key_data_byte_length) | |
68 return Status::ErrorHmacImportBadLength(); | |
69 *keylen_bits = params->optionalLengthBits(); | |
70 } | |
71 | |
72 return Status::Success(); | |
73 } | |
74 | |
25 const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash) { | 75 const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash) { |
26 switch (hash) { | 76 switch (hash) { |
27 case blink::WebCryptoAlgorithmIdSha1: | 77 case blink::WebCryptoAlgorithmIdSha1: |
28 return "HS1"; | 78 return "HS1"; |
29 case blink::WebCryptoAlgorithmIdSha256: | 79 case blink::WebCryptoAlgorithmIdSha256: |
30 return "HS256"; | 80 return "HS256"; |
31 case blink::WebCryptoAlgorithmIdSha384: | 81 case blink::WebCryptoAlgorithmIdSha384: |
32 return "HS384"; | 82 return "HS384"; |
33 case blink::WebCryptoAlgorithmIdSha512: | 83 case blink::WebCryptoAlgorithmIdSha512: |
34 return "HS512"; | 84 return "HS512"; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 blink::WebCryptoKeyUsageMask usages, | 124 blink::WebCryptoKeyUsageMask usages, |
75 GenerateKeyResult* result) const override { | 125 GenerateKeyResult* result) const override { |
76 Status status = CheckKeyCreationUsages(kAllKeyUsages, usages, false); | 126 Status status = CheckKeyCreationUsages(kAllKeyUsages, usages, false); |
77 if (status.IsError()) | 127 if (status.IsError()) |
78 return status; | 128 return status; |
79 | 129 |
80 const blink::WebCryptoHmacKeyGenParams* params = | 130 const blink::WebCryptoHmacKeyGenParams* params = |
81 algorithm.hmacKeyGenParams(); | 131 algorithm.hmacKeyGenParams(); |
82 | 132 |
83 unsigned int keylen_bits = 0; | 133 unsigned int keylen_bits = 0; |
84 status = GetHmacKeyGenLengthInBits(params, &keylen_bits); | 134 if (params->hasLengthBits()) { |
85 if (status.IsError()) | 135 keylen_bits = params->optionalLengthBits(); |
86 return status; | 136 // Zero-length HMAC keys are disallowed by the spec. |
137 if (keylen_bits == 0) | |
138 return Status::ErrorGenerateHmacKeyLengthZero(); | |
139 } else { | |
140 status = GetShaBlockSizeBits(params->hash(), &keylen_bits); | |
141 if (status.IsError()) | |
142 return status; | |
143 } | |
87 | 144 |
88 return GenerateWebCryptoSecretKey(blink::WebCryptoKeyAlgorithm::createHmac( | 145 return GenerateWebCryptoSecretKey(blink::WebCryptoKeyAlgorithm::createHmac( |
89 params->hash().id(), keylen_bits), | 146 params->hash().id(), keylen_bits), |
90 extractable, usages, keylen_bits, result); | 147 extractable, usages, keylen_bits, result); |
91 } | 148 } |
92 | 149 |
93 Status VerifyKeyUsagesBeforeImportKey( | 150 Status VerifyKeyUsagesBeforeImportKey( |
94 blink::WebCryptoKeyFormat format, | 151 blink::WebCryptoKeyFormat format, |
95 blink::WebCryptoKeyUsageMask usages) const override { | 152 blink::WebCryptoKeyUsageMask usages) const override { |
96 switch (format) { | 153 switch (format) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 bool extractable, | 196 bool extractable, |
140 blink::WebCryptoKeyUsageMask usages, | 197 blink::WebCryptoKeyUsageMask usages, |
141 blink::WebCryptoKey* key) const override { | 198 blink::WebCryptoKey* key) const override { |
142 const char* algorithm_name = | 199 const char* algorithm_name = |
143 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id()); | 200 GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id()); |
144 if (!algorithm_name) | 201 if (!algorithm_name) |
145 return Status::ErrorUnexpected(); | 202 return Status::ErrorUnexpected(); |
146 | 203 |
147 std::vector<uint8_t> raw_data; | 204 std::vector<uint8_t> raw_data; |
148 JwkReader jwk; | 205 JwkReader jwk; |
149 Status status = ReadSecretKeyNoExpectedAlg(key_data, extractable, usages, | 206 Status status = ReadSecretKeyNoExpectedAlgJwk(key_data, extractable, usages, |
150 &raw_data, &jwk); | 207 &raw_data, &jwk); |
151 if (status.IsError()) | 208 if (status.IsError()) |
152 return status; | 209 return status; |
153 status = jwk.VerifyAlg(algorithm_name); | 210 status = jwk.VerifyAlg(algorithm_name); |
154 if (status.IsError()) | 211 if (status.IsError()) |
155 return status; | 212 return status; |
156 | 213 |
157 return ImportKeyRaw(CryptoData(raw_data), algorithm, extractable, usages, | 214 return ImportKeyRaw(CryptoData(raw_data), algorithm, extractable, usages, |
158 key); | 215 key); |
159 } | 216 } |
160 | 217 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 blink::WebCryptoKeyUsageMask usages, | 272 blink::WebCryptoKeyUsageMask usages, |
216 const CryptoData& key_data, | 273 const CryptoData& key_data, |
217 blink::WebCryptoKey* key) const override { | 274 blink::WebCryptoKey* key) const override { |
218 return CreateWebCryptoSecretKey(key_data, algorithm, extractable, usages, | 275 return CreateWebCryptoSecretKey(key_data, algorithm, extractable, usages, |
219 key); | 276 key); |
220 } | 277 } |
221 | 278 |
222 Status GetKeyLength(const blink::WebCryptoAlgorithm& key_length_algorithm, | 279 Status GetKeyLength(const blink::WebCryptoAlgorithm& key_length_algorithm, |
223 bool* has_length_bits, | 280 bool* has_length_bits, |
224 unsigned int* length_bits) const override { | 281 unsigned int* length_bits) const override { |
225 return GetHmacKeyLength(key_length_algorithm, has_length_bits, length_bits); | 282 const blink::WebCryptoHmacImportParams* params = |
283 key_length_algorithm.hmacImportParams(); | |
284 | |
285 *has_length_bits = true; | |
286 if (params->hasLengthBits()) { | |
287 *length_bits = params->optionalLengthBits(); | |
288 if (*length_bits == 0) | |
289 return Status::ErrorGetHmacKeyLengthZero(); | |
290 return Status::Success(); | |
291 } | |
292 | |
293 return GetShaBlockSizeBits(params->hash(), length_bits); | |
226 } | 294 } |
227 }; | 295 }; |
228 | 296 |
229 } // namespace | 297 } // namespace |
230 | 298 |
231 scoped_ptr<AlgorithmImplementation> CreateHmacImplementation() { | 299 scoped_ptr<AlgorithmImplementation> CreateHmacImplementation() { |
232 return make_scoped_ptr(new HmacImplementation); | 300 return make_scoped_ptr(new HmacImplementation); |
233 } | 301 } |
234 | 302 |
235 } // namespace webcrypto | 303 } // namespace webcrypto |
OLD | NEW |