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" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 #include "content/renderer/webcrypto/crypto_data.h" | 14 #include "content/renderer/webcrypto/crypto_data.h" |
15 #include "content/renderer/webcrypto/platform_crypto.h" | 15 #include "content/renderer/webcrypto/platform_crypto.h" |
16 #include "content/renderer/webcrypto/shared_crypto.h" | 16 #include "content/renderer/webcrypto/shared_crypto.h" |
17 #include "content/renderer/webcrypto/webcrypto_util.h" | 17 #include "content/renderer/webcrypto/webcrypto_util.h" |
18 #include "third_party/WebKit/public/platform/WebCrypto.h" // TODO(eroman): | |
Ryan Sleevi
2014/02/25 22:26:26
What's the TODO?
eroman
2014/02/25 23:26:47
Done.
The todo is for me to delete that line. Add
| |
18 | 19 |
19 namespace content { | 20 namespace content { |
20 | 21 |
21 namespace webcrypto { | 22 namespace webcrypto { |
22 | 23 |
23 namespace { | 24 namespace { |
24 | 25 |
25 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); | 26 typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)(); |
26 | 27 |
27 class JwkAlgorithmInfo { | 28 class JwkAlgorithmInfo { |
28 public: | 29 public: |
29 JwkAlgorithmInfo() | 30 JwkAlgorithmInfo() |
30 : creation_func_(NULL), | 31 : creation_func_(NULL), |
31 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} | 32 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} |
32 | 33 |
33 explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func) | 34 explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func) |
34 : creation_func_(algorithm_creation_func), | 35 : creation_func_(algorithm_creation_func), |
35 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} | 36 required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {} |
36 | 37 |
37 JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func, | 38 JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func, |
38 unsigned int required_key_length_bits) | 39 unsigned int required_key_length_bits) |
39 : creation_func_(algorithm_creation_func), | 40 : creation_func_(algorithm_creation_func), |
40 required_key_length_bytes_(required_key_length_bits / 8) { | 41 required_key_length_bytes_(required_key_length_bits / 8) { |
41 DCHECK((required_key_length_bits % 8) == 0); | 42 DCHECK((required_key_length_bits % 8) == 0); |
42 } | 43 } |
43 | 44 |
44 bool CreateAlgorithm(blink::WebCryptoAlgorithm* algorithm) const { | 45 bool CreateImportAlgorithm(blink::WebCryptoAlgorithm* algorithm) const { |
45 *algorithm = creation_func_(); | 46 *algorithm = creation_func_(); |
46 return !algorithm->isNull(); | 47 return !algorithm->isNull(); |
47 } | 48 } |
48 | 49 |
49 bool IsInvalidKeyByteLength(size_t byte_length) const { | 50 bool IsInvalidKeyByteLength(size_t byte_length) const { |
50 if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT) | 51 if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT) |
51 return false; | 52 return false; |
52 return required_key_length_bytes_ != byte_length; | 53 return required_key_length_bytes_ != byte_length; |
53 } | 54 } |
54 | 55 |
55 private: | 56 private: |
56 enum { NO_KEY_SIZE_REQUIREMENT = UINT_MAX }; | 57 enum { NO_KEY_SIZE_REQUIREMENT = UINT_MAX }; |
57 | 58 |
58 AlgorithmCreationFunc creation_func_; | 59 AlgorithmCreationFunc creation_func_; |
59 | 60 |
60 // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT. | 61 // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT. |
61 unsigned int required_key_length_bytes_; | 62 unsigned int required_key_length_bytes_; |
62 }; | 63 }; |
63 | 64 |
64 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; | 65 typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap; |
65 | 66 |
66 class JwkAlgorithmRegistry { | 67 class JwkAlgorithmRegistry { |
67 public: | 68 public: |
68 JwkAlgorithmRegistry() { | 69 JwkAlgorithmRegistry() { |
69 // TODO(eroman): | 70 // TODO(eroman): |
70 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 | 71 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20 |
71 // says HMAC with SHA-2 should have a key size at least as large as the | 72 // says HMAC with SHA-2 should have a key size at least as large as the |
72 // hash output. | 73 // hash output. |
73 alg_to_info_["HS256"] = | 74 alg_to_info_["HS256"] = |
74 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, | 75 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
75 blink::WebCryptoAlgorithmIdSha256>); | 76 blink::WebCryptoAlgorithmIdSha256>); |
76 alg_to_info_["HS384"] = | 77 alg_to_info_["HS384"] = |
77 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, | 78 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
78 blink::WebCryptoAlgorithmIdSha384>); | 79 blink::WebCryptoAlgorithmIdSha384>); |
79 alg_to_info_["HS512"] = | 80 alg_to_info_["HS512"] = |
80 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacAlgorithmByHashId, | 81 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
81 blink::WebCryptoAlgorithmIdSha512>); | 82 blink::WebCryptoAlgorithmIdSha512>); |
82 alg_to_info_["RS256"] = | 83 alg_to_info_["RS256"] = |
83 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, | 84 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
84 blink::WebCryptoAlgorithmIdSha256>); | 85 blink::WebCryptoAlgorithmIdSha256>); |
85 alg_to_info_["RS384"] = | 86 alg_to_info_["RS384"] = |
86 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, | 87 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
87 blink::WebCryptoAlgorithmIdSha384>); | 88 blink::WebCryptoAlgorithmIdSha384>); |
88 alg_to_info_["RS512"] = | 89 alg_to_info_["RS512"] = |
89 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaAlgorithm, | 90 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
90 blink::WebCryptoAlgorithmIdSha512>); | 91 blink::WebCryptoAlgorithmIdSha512>); |
91 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 92 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
92 &BindAlgorithmId<CreateAlgorithm, | 93 &BindAlgorithmId<CreateAlgorithm, |
93 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); | 94 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>); |
94 alg_to_info_["RSA-OAEP"] = | 95 alg_to_info_["RSA-OAEP"] = |
95 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepAlgorithm, | 96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm, |
96 blink::WebCryptoAlgorithmIdSha1>); | 97 blink::WebCryptoAlgorithmIdSha1>); |
97 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet | 98 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet |
98 alg_to_info_["A128KW"] = | 99 alg_to_info_["A128KW"] = |
99 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); | 100 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 128); |
100 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet | 101 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet |
101 alg_to_info_["A256KW"] = | 102 alg_to_info_["A256KW"] = |
102 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); | 103 JwkAlgorithmInfo(&blink::WebCryptoAlgorithm::createNull, 256); |
103 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( | 104 alg_to_info_["A128GCM"] = JwkAlgorithmInfo( |
104 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>, | 105 &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>, |
105 128); | 106 128); |
(...skipping 28 matching lines...) Expand all Loading... | |
134 static blink::WebCryptoAlgorithm BindAlgorithmId() { | 135 static blink::WebCryptoAlgorithm BindAlgorithmId() { |
135 return func(algorithm_id); | 136 return func(algorithm_id); |
136 } | 137 } |
137 | 138 |
138 JwkAlgorithmInfoMap alg_to_info_; | 139 JwkAlgorithmInfoMap alg_to_info_; |
139 }; | 140 }; |
140 | 141 |
141 base::LazyInstance<JwkAlgorithmRegistry> jwk_alg_registry = | 142 base::LazyInstance<JwkAlgorithmRegistry> jwk_alg_registry = |
142 LAZY_INSTANCE_INITIALIZER; | 143 LAZY_INSTANCE_INITIALIZER; |
143 | 144 |
144 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, | 145 #ifdef WEBCRYPTO_HAS_KEY_ALGORITHM |
145 const blink::WebCryptoAlgorithm& alg2) { | 146 bool ImportAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, |
147 const blink::WebCryptoAlgorithm& alg2) { | |
146 DCHECK(!alg1.isNull()); | 148 DCHECK(!alg1.isNull()); |
147 DCHECK(!alg2.isNull()); | 149 DCHECK(!alg2.isNull()); |
148 if (alg1.id() != alg2.id()) | 150 if (alg1.id() != alg2.id()) |
151 return false; | |
152 if (alg1.paramsType() != alg2.paramsType()) | |
153 return false; | |
154 switch (alg1.paramsType()) { | |
155 case blink::WebCryptoAlgorithmParamsTypeNone: | |
156 return true; | |
157 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: | |
158 return ImportAlgorithmsConsistent(alg1.rsaHashedImportParams()->hash(), | |
159 alg2.rsaHashedImportParams()->hash()); | |
160 case blink::WebCryptoAlgorithmParamsTypeHmacImportParams: | |
161 return ImportAlgorithmsConsistent(alg1.hmacImportParams()->hash(), | |
162 alg2.hmacImportParams()->hash()); | |
163 default: | |
164 return false; | |
165 } | |
166 } | |
167 #else | |
168 bool ImportAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1, | |
169 const blink::WebCryptoAlgorithm& alg2) { | |
170 DCHECK(!alg1.isNull()); | |
171 DCHECK(!alg2.isNull()); | |
172 if (alg1.id() != alg2.id()) | |
149 return false; | 173 return false; |
150 switch (alg1.id()) { | 174 switch (alg1.id()) { |
151 case blink::WebCryptoAlgorithmIdHmac: | 175 case blink::WebCryptoAlgorithmIdHmac: |
152 case blink::WebCryptoAlgorithmIdRsaOaep: | 176 case blink::WebCryptoAlgorithmIdRsaOaep: |
153 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 177 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
154 if (WebCryptoAlgorithmsConsistent(GetInnerHashAlgorithm(alg1), | 178 if (ImportAlgorithmsConsistent(GetInnerHashAlgorithm(alg1), |
155 GetInnerHashAlgorithm(alg2))) { | 179 GetInnerHashAlgorithm(alg2))) { |
156 return true; | 180 return true; |
157 } | 181 } |
158 break; | 182 break; |
159 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 183 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
160 case blink::WebCryptoAlgorithmIdSha1: | 184 case blink::WebCryptoAlgorithmIdSha1: |
161 case blink::WebCryptoAlgorithmIdSha224: | 185 case blink::WebCryptoAlgorithmIdSha224: |
162 case blink::WebCryptoAlgorithmIdSha256: | 186 case blink::WebCryptoAlgorithmIdSha256: |
163 case blink::WebCryptoAlgorithmIdSha384: | 187 case blink::WebCryptoAlgorithmIdSha384: |
164 case blink::WebCryptoAlgorithmIdSha512: | 188 case blink::WebCryptoAlgorithmIdSha512: |
165 case blink::WebCryptoAlgorithmIdAesCbc: | 189 case blink::WebCryptoAlgorithmIdAesCbc: |
166 case blink::WebCryptoAlgorithmIdAesGcm: | 190 case blink::WebCryptoAlgorithmIdAesGcm: |
167 case blink::WebCryptoAlgorithmIdAesCtr: | 191 case blink::WebCryptoAlgorithmIdAesCtr: |
168 return true; | 192 return true; |
169 default: | 193 default: |
170 NOTREACHED(); // Not a supported algorithm. | 194 NOTREACHED(); // Not a supported algorithm. |
171 break; | 195 break; |
172 } | 196 } |
173 return false; | 197 return false; |
174 } | 198 } |
199 #endif | |
175 | 200 |
176 // Extracts the required string property with key |path| from |dict| and saves | 201 // Extracts the required string property with key |path| from |dict| and saves |
177 // the result to |*result|. If the property does not exist or is not a string, | 202 // the result to |*result|. If the property does not exist or is not a string, |
178 // returns an error. | 203 // returns an error. |
179 Status GetJwkString(base::DictionaryValue* dict, | 204 Status GetJwkString(base::DictionaryValue* dict, |
180 const std::string& path, | 205 const std::string& path, |
181 std::string* result) { | 206 std::string* result) { |
182 base::Value* value = NULL; | 207 base::Value* value = NULL; |
183 if (!dict->Get(path, &value)) | 208 if (!dict->Get(path, &value)) |
184 return Status::ErrorJwkPropertyMissing(path); | 209 return Status::ErrorJwkPropertyMissing(path); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 | 466 |
442 if (has_jwk_alg) { | 467 if (has_jwk_alg) { |
443 // JWK alg present | 468 // JWK alg present |
444 | 469 |
445 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can | 470 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can |
446 // only be from the RSA family. | 471 // only be from the RSA family. |
447 | 472 |
448 blink::WebCryptoAlgorithm jwk_algorithm = | 473 blink::WebCryptoAlgorithm jwk_algorithm = |
449 blink::WebCryptoAlgorithm::createNull(); | 474 blink::WebCryptoAlgorithm::createNull(); |
450 algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value); | 475 algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value); |
451 if (!algorithm_info || !algorithm_info->CreateAlgorithm(&jwk_algorithm)) | 476 if (!algorithm_info || |
477 !algorithm_info->CreateImportAlgorithm(&jwk_algorithm)) | |
452 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 | 478 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1 |
453 | 479 |
454 // JWK alg valid | 480 // JWK alg valid |
455 if (algorithm_or_null.isNull()) { | 481 if (algorithm_or_null.isNull()) { |
456 // input algorithm not specified | 482 // input algorithm not specified |
457 algorithm = jwk_algorithm; // case 2 | 483 algorithm = jwk_algorithm; // case 2 |
458 } else { | 484 } else { |
459 // input algorithm specified | 485 // input algorithm specified |
460 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) | 486 if (!ImportAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) |
461 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 | 487 return Status::ErrorJwkAlgorithmInconsistent(); // case 3 |
462 algorithm = algorithm_or_null; // case 4 | 488 algorithm = algorithm_or_null; // case 4 |
463 } | 489 } |
464 } else { | 490 } else { |
465 // JWK alg missing | 491 // JWK alg missing |
466 if (algorithm_or_null.isNull()) | 492 if (algorithm_or_null.isNull()) |
467 return Status::ErrorJwkAlgorithmMissing(); // case 5 | 493 return Status::ErrorJwkAlgorithmMissing(); // case 5 |
468 algorithm = algorithm_or_null; // case 6 | 494 algorithm = algorithm_or_null; // case 6 |
469 } | 495 } |
470 DCHECK(!algorithm.isNull()); | 496 DCHECK(!algorithm.isNull()); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 } else { | 580 } else { |
555 return Status::ErrorJwkUnrecognizedKty(); | 581 return Status::ErrorJwkUnrecognizedKty(); |
556 } | 582 } |
557 | 583 |
558 return Status::Success(); | 584 return Status::Success(); |
559 } | 585 } |
560 | 586 |
561 } // namespace webcrypto | 587 } // namespace webcrypto |
562 | 588 |
563 } // namespace content | 589 } // namespace content |
OLD | NEW |