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