| 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 |