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 |