| 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 <algorithm> | 5 #include <algorithm> |
| 6 #include <functional> | 6 #include <functional> |
| 7 #include <map> | 7 #include <map> |
| 8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 namespace webcrypto { | 21 namespace webcrypto { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); | 25 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
| 26 | 26 |
| 27 class JwkAlgorithmInfo { | 27 class JwkAlgorithmInfo { |
| 28 public: | 28 public: |
| 29 JwkAlgorithmInfo() | 29 JwkAlgorithmInfo() |
| 30 : creation_func_(NULL), | 30 : creation_func_(NULL), |
| 31 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { | 31 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} |
| 32 | |
| 33 } | |
| 34 | 32 |
| 35 explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func) | 33 explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func) |
| 36 : creation_func_(algorithm_creation_func), | 34 : creation_func_(algorithm_creation_func), |
| 37 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) { | 35 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} |
| 38 } | |
| 39 | 36 |
| 40 JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func, | 37 JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func, |
| 41 unsigned int required_key_length_bits) | 38 unsigned int required_key_length_bits) |
| 42 : creation_func_(algorithm_creation_func), | 39 : creation_func_(algorithm_creation_func), |
| 43 required_key_length_bytes_(required_key_length_bits / 8) { | 40 required_key_length_bytes_(required_key_length_bits / 8) { |
| 44 DCHECK((required_key_length_bits % 8) == 0); | 41 DCHECK((required_key_length_bits % 8) == 0); |
| 45 } | 42 } |
| 46 | 43 |
| 47 bool CreateAlgorithm(blink::WebCryptoAlgorithm* algorithm) const { | 44 bool CreateAlgorithm(blink::WebCryptoAlgorithm* algorithm) const { |
| 48 *algorithm = creation_func_(); | 45 *algorithm = creation_func_(); |
| 49 return !algorithm->isNull(); | 46 return !algorithm->isNull(); |
| 50 } | 47 } |
| 51 | 48 |
| 52 bool IsInvalidKeyByteLength(size_t byte_length) const { | 49 bool IsInvalidKeyByteLength(size_t byte_length) const { |
| 53 if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT) | 50 if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT) |
| 54 return false; | 51 return false; |
| 55 return required_key_length_bytes_ != byte_length; | 52 return required_key_length_bytes_ != byte_length; |
| 56 } | 53 } |
| 57 | 54 |
| 58 private: | 55 private: |
| 59 enum { NO_KEY_SIZE_REQUIREMENT = UINT_MAX }; | 56 enum { NO_KEY_SIZE_REQUIREMENT = UINT_MAX }; |
| 60 | 57 |
| 61 AlgorithmCreationFunc creation_func_; | 58 AlgorithmCreationFunc creation_func_; |
| 62 | 59 |
| 63 // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT. | 60 // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT. |
| 64 unsigned int required_key_length_bytes_; | 61 unsigned int required_key_length_bytes_; |
| 65 | |
| 66 }; | 62 }; |
| 67 | 63 |
| 68 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; | 64 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
| 69 | 65 |
| 70 class JwkAlgorithmRegistry { | 66 class JwkAlgorithmRegistry { |
| 71 public: | 67 public: |
| 72 JwkAlgorithmRegistry() { | 68 JwkAlgorithmRegistry() { |
| 73 // TODO(eroman): | 69 // TODO(eroman): |
| 74 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | 70 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 |
| 75 // says HMAC with SHA-2 should have a key size at least as large as the | 71 // says HMAC with SHA-2 should have a key size at least as large as the |
| 76 // hash output. | 72 // hash output. |
| 77 alg_to_info_["HS256"] = JwkAlgorithmInfo( | 73 alg_to_info_["HS256"] = |
| 78 &BindAlgorithmId<CreateHmacAlgorithmByHashId, | 74 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 79 blink::WebCryptoAlgorithmIdSha256>); | 75 blink::WebCryptoAlgorithmIdSha256>); |
| 80 alg_to_info_["HS384"] = JwkAlgorithmInfo( | 76 alg_to_info_["HS384"] = |
| 81 &BindAlgorithmId<CreateHmacAlgorithmByHashId, | 77 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 82 blink::WebCryptoAlgorithmIdSha384>); | 78 blink::WebCryptoAlgorithmIdSha384>); |
| 83 alg_to_info_["HS512"] = JwkAlgorithmInfo( | 79 alg_to_info_["HS512"] = |
| 84 &BindAlgorithmId<CreateHmacAlgorithmByHashId, | 80 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, |
| 85 blink::WebCryptoAlgorithmIdSha512>); | 81 blink::WebCryptoAlgorithmIdSha512>); |
| 86 alg_to_info_["RS256"] = JwkAlgorithmInfo( | 82 alg_to_info_["RS256"] = |
| 87 &BindAlgorithmId<CreateRsaSsaAlgorithm, | 83 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 88 blink::WebCryptoAlgorithmIdSha256>); | 84 blink::WebCryptoAlgorithmIdSha256>); |
| 89 alg_to_info_["RS384"] = JwkAlgorithmInfo( | 85 alg_to_info_["RS384"] = |
| 90 &BindAlgorithmId<CreateRsaSsaAlgorithm, | 86 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 91 blink::WebCryptoAlgorithmIdSha384>); | 87 blink::WebCryptoAlgorithmIdSha384>); |
| 92 alg_to_info_["RS512"] = JwkAlgorithmInfo( | 88 alg_to_info_["RS512"] = |
| 93 &BindAlgorithmId<CreateRsaSsaAlgorithm, | 89 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, |
| 94 blink::WebCryptoAlgorithmIdSha512>); | 90 blink::WebCryptoAlgorithmIdSha512>); |
| 95 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 91 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
| 96 &BindAlgorithmId<CreateAlgorithm, | 92 &BindAlgorithmId<CreateAlgorithm, |
| 97 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | 93 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); |
| 98 alg_to_info_["RSA-OAEP"] = JwkAlgorithmInfo( | 94 alg_to_info_["RSA-OAEP"] = |
| 99 &BindAlgorithmId<CreateRsaOaepAlgorithm, | 95 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepAlgorithm, |
| 100 blink::WebCryptoAlgorithmIdSha1>); | 96 blink::WebCryptoAlgorithmIdSha1>); |
| 101 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | 97 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet |
| 102 alg_to_info_["A128KW"] = | 98 alg_to_info_["A128KW"] = |
| 103 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); | 99 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); |
| 104 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | 100 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet |
| 105 alg_to_info_["A256KW"] = | 101 alg_to_info_["A256KW"] = |
| 106 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); | 102 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); |
| 107 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | 103 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( |
| 108 &BindAlgorithmId<CreateAlgorithm, | 104 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>, |
| 109 blink::WebCryptoAlgorithmIdAesGcm>, 128); | 105 128); |
| 110 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( | 106 alg_to_info_["A256GCM"] = JwkAlgorithmInfo( |
| 111 &BindAlgorithmId<CreateAlgorithm, | 107 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>, |
| 112 blink::WebCryptoAlgorithmIdAesGcm>, 256); | 108 256); |
| 113 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( | 109 alg_to_info_["A128CBC"] = JwkAlgorithmInfo( |
| 114 &BindAlgorithmId<CreateAlgorithm, | 110 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>, |
| 115 blink::WebCryptoAlgorithmIdAesCbc>, 128); | 111 128); |
| 116 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( | 112 alg_to_info_["A192CBC"] = JwkAlgorithmInfo( |
| 117 &BindAlgorithmId<CreateAlgorithm, | 113 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>, |
| 118 blink::WebCryptoAlgorithmIdAesCbc>, 192); | 114 192); |
| 119 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( | 115 alg_to_info_["A256CBC"] = JwkAlgorithmInfo( |
| 120 &BindAlgorithmId<CreateAlgorithm, | 116 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>, |
| 121 blink::WebCryptoAlgorithmIdAesCbc>, 256); | 117 256); |
| 122 } | 118 } |
| 123 | 119 |
| 124 // Returns NULL if the algorithm name was not registered. | 120 // Returns NULL if the algorithm name was not registered. |
| 125 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { | 121 const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const { |
| 126 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); | 122 const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg); |
| 127 if (pos == alg_to_info_.end()) | 123 if (pos == alg_to_info_.end()) |
| 128 return NULL; | 124 return NULL; |
| 129 return &pos->second; | 125 return &pos->second; |
| 130 } | 126 } |
| 131 | 127 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 148 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, | 144 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, |
| 149 const blink::WebCryptoAlgorithm& alg2) { | 145 const blink::WebCryptoAlgorithm& alg2) { |
| 150 DCHECK(!alg1.isNull()); | 146 DCHECK(!alg1.isNull()); |
| 151 DCHECK(!alg2.isNull()); | 147 DCHECK(!alg2.isNull()); |
| 152 if (alg1.id() != alg2.id()) | 148 if (alg1.id() != alg2.id()) |
| 153 return false; | 149 return false; |
| 154 switch (alg1.id()) { | 150 switch (alg1.id()) { |
| 155 case blink::WebCryptoAlgorithmIdHmac: | 151 case blink::WebCryptoAlgorithmIdHmac: |
| 156 case blink::WebCryptoAlgorithmIdRsaOaep: | 152 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 157 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 153 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 158 if (WebCryptoAlgorithmsConsistent( | 154 if (WebCryptoAlgorithmsConsistent(GetInnerHashAlgorithm(alg1), |
| 159 GetInnerHashAlgorithm(alg1), | 155 GetInnerHashAlgorithm(alg2))) { |
| 160 GetInnerHashAlgorithm(alg2))) { | |
| 161 return true; | 156 return true; |
| 162 } | 157 } |
| 163 break; | 158 break; |
| 164 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 159 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| 165 case blink::WebCryptoAlgorithmIdSha1: | 160 case blink::WebCryptoAlgorithmIdSha1: |
| 166 case blink::WebCryptoAlgorithmIdSha224: | 161 case blink::WebCryptoAlgorithmIdSha224: |
| 167 case blink::WebCryptoAlgorithmIdSha256: | 162 case blink::WebCryptoAlgorithmIdSha256: |
| 168 case blink::WebCryptoAlgorithmIdSha384: | 163 case blink::WebCryptoAlgorithmIdSha384: |
| 169 case blink::WebCryptoAlgorithmIdSha512: | 164 case blink::WebCryptoAlgorithmIdSha512: |
| 170 case blink::WebCryptoAlgorithmIdAesCbc: | 165 case blink::WebCryptoAlgorithmIdAesCbc: |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 | 239 |
| 245 if (!value->GetAsBoolean(result)) | 240 if (!value->GetAsBoolean(result)) |
| 246 return Status::ErrorJwkPropertyWrongType(path, "boolean"); | 241 return Status::ErrorJwkPropertyWrongType(path, "boolean"); |
| 247 | 242 |
| 248 *property_exists = true; | 243 *property_exists = true; |
| 249 return Status::Success(); | 244 return Status::Success(); |
| 250 } | 245 } |
| 251 | 246 |
| 252 } // namespace | 247 } // namespace |
| 253 | 248 |
| 254 Status ImportKeyJwk( | 249 Status ImportKeyJwk(const CryptoData& key_data, |
| 255 const CryptoData& key_data, | 250 const blink::WebCryptoAlgorithm& algorithm_or_null, |
| 256 const blink::WebCryptoAlgorithm& algorithm_or_null, | 251 bool extractable, |
| 257 bool extractable, | 252 blink::WebCryptoKeyUsageMask usage_mask, |
| 258 blink::WebCryptoKeyUsageMask usage_mask, | 253 blink::WebCryptoKey* key) { |
| 259 blink::WebCryptoKey* key) { | |
| 260 | 254 |
| 261 // The goal of this method is to extract key material and meta data from the | 255 // The goal of this method is to extract key material and meta data from the |
| 262 // incoming JWK, combine them with the input parameters, and ultimately import | 256 // incoming JWK, combine them with the input parameters, and ultimately import |
| 263 // a Web Crypto Key. | 257 // a Web Crypto Key. |
| 264 // | 258 // |
| 265 // JSON Web Key Format (JWK) | 259 // JSON Web Key Format (JWK) |
| 266 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 | 260 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16 |
| 267 // TODO(padolph): Not all possible values are handled by this code right now | 261 // TODO(padolph): Not all possible values are handled by this code right now |
| 268 // | 262 // |
| 269 // A JWK is a simple JSON dictionary with the following entries | 263 // A JWK is a simple JSON dictionary with the following entries |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 | 452 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 |
| 459 | 453 |
| 460 // JWK alg valid | 454 // JWK alg valid |
| 461 if (algorithm_or_null.isNull()) { | 455 if (algorithm_or_null.isNull()) { |
| 462 // input algorithm not specified | 456 // input algorithm not specified |
| 463 algorithm = jwk_algorithm; // case 2 | 457 algorithm = jwk_algorithm; // case 2 |
| 464 } else { | 458 } else { |
| 465 // input algorithm specified | 459 // input algorithm specified |
| 466 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) | 460 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) |
| 467 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 | 461 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 |
| 468 algorithm = algorithm_or_null; // case 4 | 462 algorithm = algorithm_or_null; // case 4 |
| 469 } | 463 } |
| 470 } else { | 464 } else { |
| 471 // JWK alg missing | 465 // JWK alg missing |
| 472 if (algorithm_or_null.isNull()) | 466 if (algorithm_or_null.isNull()) |
| 473 return Status::ErrorJwkAlgorithmMissing(); // case 5 | 467 return Status::ErrorJwkAlgorithmMissing(); // case 5 |
| 474 algorithm = algorithm_or_null; // case 6 | 468 algorithm = algorithm_or_null; // case 6 |
| 475 } | 469 } |
| 476 DCHECK(!algorithm.isNull()); | 470 DCHECK(!algorithm.isNull()); |
| 477 | 471 |
| 478 // JWK "use" (optional) --> usage_mask parameter | 472 // JWK "use" (optional) --> usage_mask parameter |
| 479 std::string jwk_use_value; | 473 std::string jwk_use_value; |
| 480 bool has_jwk_use; | 474 bool has_jwk_use; |
| 481 status = | 475 status = |
| 482 GetOptionalJwkString(dict_value, "use", &jwk_use_value, &has_jwk_use); | 476 GetOptionalJwkString(dict_value, "use", &jwk_use_value, &has_jwk_use); |
| 483 if (status.IsError()) | 477 if (status.IsError()) |
| 484 return status; | 478 return status; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 } else { | 554 } else { |
| 561 return Status::ErrorJwkUnrecognizedKty(); | 555 return Status::ErrorJwkUnrecognizedKty(); |
| 562 } | 556 } |
| 563 | 557 |
| 564 return Status::Success(); | 558 return Status::Success(); |
| 565 } | 559 } |
| 566 | 560 |
| 567 } // namespace webcrypto | 561 } // namespace webcrypto |
| 568 | 562 |
| 569 } // namespace content | 563 } // namespace content |
| OLD | NEW |