OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "content/renderer/webcrypto/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <map> | |
9 #include "base/base64.h" | |
10 #include "base/json/json_reader.h" | |
11 #include "base/logging.h" | |
7 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/strings/string_piece.h" | |
14 #include "base/values.h" | |
8 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | 15 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
9 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
10 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | 18 #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
11 | 19 |
12 namespace content { | 20 namespace content { |
13 | 21 |
22 namespace { | |
23 | |
24 // TODO(padolph) Similar Create*Algorithm() methods are in | |
25 // webcrypto_impl_unittest.cc. Find a common place to put these. | |
26 | |
27 WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) { | |
28 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); | |
29 } | |
30 | |
31 WebKit::WebCryptoAlgorithm CreateAlgorithmWithInnerHash( | |
32 WebKit::WebCryptoAlgorithmId algorithm_id, | |
33 unsigned short hash_key_length) { | |
34 WebKit::WebCryptoAlgorithmId hashId; | |
35 switch (hash_key_length) { | |
36 case 160: | |
37 hashId = WebKit::WebCryptoAlgorithmIdSha1; | |
38 break; | |
39 case 224: | |
40 hashId = WebKit::WebCryptoAlgorithmIdSha224; | |
41 break; | |
42 case 256: | |
43 hashId = WebKit::WebCryptoAlgorithmIdSha256; | |
44 break; | |
45 case 384: | |
46 hashId = WebKit::WebCryptoAlgorithmIdSha384; | |
47 break; | |
48 case 512: | |
49 hashId = WebKit::WebCryptoAlgorithmIdSha384; | |
50 break; | |
51 } | |
52 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
53 algorithm_id, | |
54 new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId))); | |
55 } | |
56 | |
57 WebKit::WebCryptoAlgorithm CreateHmacAlgorithm(unsigned short hash_key_length) { | |
58 return CreateAlgorithmWithInnerHash( | |
59 WebKit::WebCryptoAlgorithmIdHmac, | |
60 hash_key_length); | |
61 } | |
62 | |
63 WebKit::WebCryptoAlgorithm CreateRsaSsaAlgorithm( | |
64 unsigned short hash_key_length) { | |
65 return CreateAlgorithmWithInnerHash( | |
66 WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, | |
67 hash_key_length); | |
68 } | |
69 | |
70 WebKit::WebCryptoAlgorithm CreateRsaOaepAlgorithm( | |
71 unsigned short hash_key_length) { | |
72 return CreateAlgorithmWithInnerHash( | |
73 WebKit::WebCryptoAlgorithmIdRsaOaep, | |
74 hash_key_length); | |
75 } | |
76 | |
77 WebKit::WebCryptoAlgorithm CreateAesAlgorithm( | |
78 WebKit::WebCryptoAlgorithmId aes_alg_id, | |
79 unsigned short length) { | |
80 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
81 aes_alg_id, | |
82 new WebKit::WebCryptoAesKeyGenParams(length)); | |
83 } | |
84 | |
85 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(unsigned short length) { | |
86 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc, length); | |
87 } | |
88 | |
89 WebKit::WebCryptoAlgorithm CreateAesGcmAlgorithm(unsigned short length) { | |
90 return CreateAesAlgorithm(WebKit::WebCryptoAlgorithmIdAesGcm, length); | |
91 } | |
92 | |
93 bool Base64DecodeUrlSafe(const std::string& input, std::string* output) { | |
94 std::string base64EncodedText(input); | |
95 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+'); | |
96 std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/'); | |
97 base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '='); | |
98 return base::Base64Decode(base64EncodedText, output); | |
99 } | |
100 | |
101 // Identifiers for all JWK "alg" (algorithm) values handled by this code. The | |
102 // "enum trick" is used to force int type, so a user type is not required in | |
103 // web_crypto_impl.h | |
104 enum { | |
105 kJwkAlgorithmHs256, | |
106 kJwkAlgorithmHs384, | |
107 kJwkAlgorithmHs512, | |
108 kJwkAlgorithmRs256, | |
109 kJwkAlgorithmRs384, | |
110 kJwkAlgorithmRs512, | |
111 kJwkAlgorithmRsa1_5, | |
112 kJwkAlgorithmRsaOaep, | |
113 kJwkAlgorithmA128Kw, | |
114 kJwkAlgorithmA256Kw, | |
115 kJwkAlgorithmA128Gcm, | |
116 kJwkAlgorithmA256Gcm, | |
117 kJwkAlgorithmA128Cbc, | |
118 kJwkAlgorithmA256Cbc, | |
119 kJwkAlgorithmA384Cbc, | |
120 kJwkAlgorithmA512Cbc | |
121 }; | |
122 | |
123 WebKit::WebCryptoAlgorithmId JwkAlgIdToWebCryptoAlgId(int jwk_algorithm_id) { | |
124 switch (jwk_algorithm_id) { | |
125 case kJwkAlgorithmHs256: | |
126 case kJwkAlgorithmHs384: | |
127 case kJwkAlgorithmHs512: | |
128 return WebKit::WebCryptoAlgorithmIdHmac; | |
129 case kJwkAlgorithmRs256: | |
130 case kJwkAlgorithmRs384: | |
131 case kJwkAlgorithmRs512: | |
132 return WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | |
133 case kJwkAlgorithmRsa1_5: | |
134 return WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5; | |
135 case kJwkAlgorithmRsaOaep: | |
136 return WebKit::WebCryptoAlgorithmIdRsaOaep; | |
137 case kJwkAlgorithmA128Kw: | |
138 case kJwkAlgorithmA256Kw: | |
139 // TODO(padolph) Support AES keywrap algorithm, required for JWK but not | |
140 // present in the Web Crypto spec. | |
141 return WebKit::WebCryptoAlgorithmIdNone; | |
142 case kJwkAlgorithmA128Gcm: | |
143 case kJwkAlgorithmA256Gcm: | |
144 return WebKit::WebCryptoAlgorithmIdAesGcm; | |
145 case kJwkAlgorithmA128Cbc: | |
146 case kJwkAlgorithmA256Cbc: | |
147 case kJwkAlgorithmA384Cbc: | |
148 case kJwkAlgorithmA512Cbc: | |
149 return WebKit::WebCryptoAlgorithmIdAesCbc; | |
150 default: | |
151 DCHECK(false); | |
152 return WebKit::WebCryptoAlgorithmIdNone; | |
153 } | |
154 } | |
155 | |
156 unsigned short JwkAlgIdToKeyLengthBits(int jwk_algorithm_id) { | |
157 switch (jwk_algorithm_id) { | |
158 case kJwkAlgorithmA128Kw: | |
159 case kJwkAlgorithmA128Gcm: | |
160 case kJwkAlgorithmA128Cbc: | |
161 return 128; | |
162 case kJwkAlgorithmHs256: | |
163 case kJwkAlgorithmA256Kw: | |
164 case kJwkAlgorithmRs256: | |
165 case kJwkAlgorithmA256Gcm: | |
166 case kJwkAlgorithmA256Cbc: | |
167 return 256; | |
168 case kJwkAlgorithmHs384: | |
169 case kJwkAlgorithmRs384: | |
170 case kJwkAlgorithmA384Cbc: | |
171 return 384; | |
172 case kJwkAlgorithmHs512: | |
173 case kJwkAlgorithmRs512: | |
174 case kJwkAlgorithmA512Cbc: | |
175 return 512; | |
176 default: | |
177 return 0; | |
178 } | |
179 } | |
180 | |
181 typedef std::map<std::string, int> StringIntMap; | |
182 | |
183 // Syntactic sugar to make runtime initialization of a std::map more palatable, | |
184 // similar to what you can do in C++11 or with Boost.Assign. | |
185 // Example: | |
186 // StringIntMap my_map; | |
187 // // instead of this | |
188 // my_map.insert(std::make_pair("a", 1); | |
189 // my_map.insert(std::make_pair("b", 2); | |
190 // my_map.insert(std::make_pair("c", 3); | |
191 // my_map.insert(std::make_pair("d", 4); | |
192 // // do this | |
193 // map_fill<StringIntMap> | |
194 // ("a", 1) | |
195 // ("b", 2) | |
196 // ("c", 3) | |
197 // ("d", 4) | |
198 // .to(my_map); | |
Ryan Sleevi
2013/10/04 23:19:11
Why is this syntactic sugar needed, when
my_map["
padolph
2013/10/05 02:57:42
Done.
| |
199 template <typename MapType> | |
200 class FillMap { | |
201 public: | |
202 typedef typename MapType::key_type KeyType; | |
203 typedef typename MapType::mapped_type MappedType; | |
204 FillMap(const KeyType& key, const MappedType& val) { operator()(key, val); } | |
205 FillMap& operator()(const KeyType& key, const MappedType& val) { | |
206 map_.insert(std::make_pair(key, val)); | |
207 return *this; | |
208 } | |
209 void to(MapType& map) { map.swap(map_); } | |
210 private: | |
211 MapType map_; | |
212 }; | |
213 | |
214 void InitJwkAlgorithmMap(StringIntMap& jwk_algorithm_map) | |
215 { | |
216 // Note: A*CBC are not yet present in the JOSE JWA spec | |
217 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 | |
218 FillMap<StringIntMap> | |
219 ("HS256" , kJwkAlgorithmHs256 ) | |
220 ("HS384" , kJwkAlgorithmHs384 ) | |
221 ("HS512" , kJwkAlgorithmHs512 ) | |
222 ("RS256" , kJwkAlgorithmRs256 ) | |
223 ("RS384" , kJwkAlgorithmRs384 ) | |
224 ("RS512" , kJwkAlgorithmRs512 ) | |
225 ("RSA1_5" , kJwkAlgorithmRsa1_5 ) | |
226 ("RSA-OAEP", kJwkAlgorithmRsaOaep) | |
227 ("A128KW" , kJwkAlgorithmA128Kw ) | |
228 ("A256KW" , kJwkAlgorithmA256Kw ) | |
229 ("A128GCM" , kJwkAlgorithmA128Gcm) | |
230 ("A256GCM" , kJwkAlgorithmA256Gcm) | |
231 ("A128CBC" , kJwkAlgorithmA128Cbc) | |
232 ("A256CBC" , kJwkAlgorithmA256Cbc) | |
233 ("A384CBC" , kJwkAlgorithmA384Cbc) | |
234 ("A512CBC" , kJwkAlgorithmA512Cbc) | |
235 .to(jwk_algorithm_map); | |
236 } | |
237 | |
238 } // namespace | |
239 | |
14 WebCryptoImpl::WebCryptoImpl() { | 240 WebCryptoImpl::WebCryptoImpl() { |
15 Init(); | 241 Init(); |
242 InitJwkAlgorithmMap(jwk_algorithm_map_); | |
16 } | 243 } |
17 | 244 |
18 void WebCryptoImpl::encrypt( | 245 void WebCryptoImpl::encrypt( |
19 const WebKit::WebCryptoAlgorithm& algorithm, | 246 const WebKit::WebCryptoAlgorithm& algorithm, |
20 const WebKit::WebCryptoKey& key, | 247 const WebKit::WebCryptoKey& key, |
21 const unsigned char* data, | 248 const unsigned char* data, |
22 unsigned data_size, | 249 unsigned data_size, |
23 WebKit::WebCryptoResult result) { | 250 WebKit::WebCryptoResult result) { |
24 WebKit::WebArrayBuffer buffer; | 251 WebKit::WebArrayBuffer buffer; |
25 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { | 252 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 void WebCryptoImpl::importKey( | 286 void WebCryptoImpl::importKey( |
60 WebKit::WebCryptoKeyFormat format, | 287 WebKit::WebCryptoKeyFormat format, |
61 const unsigned char* key_data, | 288 const unsigned char* key_data, |
62 unsigned key_data_size, | 289 unsigned key_data_size, |
63 const WebKit::WebCryptoAlgorithm& algorithm, | 290 const WebKit::WebCryptoAlgorithm& algorithm, |
64 bool extractable, | 291 bool extractable, |
65 WebKit::WebCryptoKeyUsageMask usage_mask, | 292 WebKit::WebCryptoKeyUsageMask usage_mask, |
66 WebKit::WebCryptoResult result) { | 293 WebKit::WebCryptoResult result) { |
67 WebKit::WebCryptoKeyType type; | 294 WebKit::WebCryptoKeyType type; |
68 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; | 295 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; |
296 WebKit::WebCryptoAlgorithm modified_algorithm = algorithm; | |
69 | 297 |
70 if (!ImportKeyInternal(format, | 298 if (format == WebKit::WebCryptoKeyFormatJwk) { |
71 key_data, | 299 if (!ImportKeyJwk(key_data, |
72 key_data_size, | 300 key_data_size, |
73 algorithm, | 301 &handle, |
74 usage_mask, | 302 &type, |
75 &handle, | 303 &extractable, |
76 &type)) { | 304 &modified_algorithm, |
77 result.completeWithError(); | 305 &usage_mask)) { |
78 return; | 306 result.completeWithError(); |
307 } | |
308 } else { | |
309 if (!ImportKeyInternal(format, | |
310 key_data, | |
311 key_data_size, | |
312 modified_algorithm, | |
313 usage_mask, | |
314 &handle, | |
315 &type)) { | |
316 result.completeWithError(); | |
317 } | |
79 } | 318 } |
80 | 319 |
81 WebKit::WebCryptoKey key( | 320 WebKit::WebCryptoKey key(WebKit::WebCryptoKey::create( |
82 WebKit::WebCryptoKey::create( | 321 handle.release(), type, extractable, modified_algorithm, usage_mask)); |
83 handle.release(), type, extractable, algorithm, usage_mask)); | |
84 | 322 |
85 result.completeWithKey(key); | 323 result.completeWithKey(key); |
86 } | 324 } |
87 | 325 |
88 void WebCryptoImpl::sign( | 326 void WebCryptoImpl::sign( |
89 const WebKit::WebCryptoAlgorithm& algorithm, | 327 const WebKit::WebCryptoAlgorithm& algorithm, |
90 const WebKit::WebCryptoKey& key, | 328 const WebKit::WebCryptoKey& key, |
91 const unsigned char* data, | 329 const unsigned char* data, |
92 unsigned data_size, | 330 unsigned data_size, |
93 WebKit::WebCryptoResult result) { | 331 WebKit::WebCryptoResult result) { |
(...skipping 20 matching lines...) Expand all Loading... | |
114 signature_size, | 352 signature_size, |
115 data, | 353 data, |
116 data_size, | 354 data_size, |
117 &signature_match)) { | 355 &signature_match)) { |
118 result.completeWithError(); | 356 result.completeWithError(); |
119 } else { | 357 } else { |
120 result.completeWithBoolean(signature_match); | 358 result.completeWithBoolean(signature_match); |
121 } | 359 } |
122 } | 360 } |
123 | 361 |
362 bool WebCryptoImpl::ImportKeyJwk( | |
363 const unsigned char* key_data, | |
364 unsigned key_data_size, | |
365 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, | |
366 WebKit::WebCryptoKeyType* type, | |
367 bool* extractable, | |
368 WebKit::WebCryptoAlgorithm* algorithm, | |
369 WebKit::WebCryptoKeyUsageMask* usage_mask) { | |
370 | |
371 // JSON Web Key Format (JWK) | |
372 // http://self-issued.info/docs/draft-ietf-jose-json-web-key.html (JOSE) | |
Ryan Sleevi
2013/10/04 23:19:11
Let's refer to a canonical draft URL at the IETF,
padolph
2013/10/05 02:57:42
Done.
| |
373 // TODO(padolph) Not all possible values are handled by this code right now | |
374 // | |
375 // A JWK is a simple JSON dictionary with the following entries | |
376 // - "kty" (Key Type) Parameter, REQUIRED | |
377 // - <kty-specific parameters, see below>, REQUIRED | |
378 // - "use" (Key Use) Parameter, OPTIONAL | |
379 // - "alg" (Algorithm) Parameter, OPTIONAL | |
380 // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE] | |
381 // (all other entries are ignored) | |
382 // | |
383 // Input key_data contains the JWK. To build a Web Crypto Key, the JWK values | |
384 // are parsed out and used as follows: | |
385 // Web Crypto Key type <-- (deduced) | |
386 // Web Crypto Key extractable <-- extractable | |
387 // Web Crypto Key algorithm <-- alg | |
388 // Web Crypto Key keyUsage <-- usage | |
389 // Web Crypto Key keying material <-- kty-specific parameters | |
390 // | |
391 // Values for each entry are case-sensitive and defined in | |
392 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16. | |
393 // Note that not all values specified by JOSE are handled by this code. Only | |
394 // handled values are listed. | |
395 // - kty (Key Type) | |
396 // +-------+--------------------------------------------------------------+ | |
397 // | "RSA" | RSA [RFC3447] | | |
398 // | "oct" | Octet sequence (used to represent symmetric keys) | | |
399 // +-------+--------------------------------------------------------------+ | |
400 // - use (Key Use) | |
401 // +-------+--------------------------------------------------------------+ | |
402 // | "enc" | encrypt and decrypt operations | | |
403 // | "sig" | sign and verify (MAC) operations | | |
404 // | "wrap"| key wrap and unwrap [not yet part of JOSE] | | |
405 // +-------+--------------------------------------------------------------+ | |
406 // - extractable (Key Exportability) | |
407 // +-------+--------------------------------------------------------------+ | |
408 // | true | Key may be exported from the trusted environment | | |
409 // | false | Key cannot exit the trusted environment | | |
410 // +-------+--------------------------------------------------------------+ | |
411 // - alg (Algorithm) | |
412 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16 | |
413 // +--------------+-------------------------------------------------------+ | |
414 // | Digital Signature or MAC Algorithm | | |
415 // +--------------+-------------------------------------------------------+ | |
416 // | "HS256" | HMAC using SHA-256 hash algorithm | | |
417 // | "HS384" | HMAC using SHA-384 hash algorithm | | |
418 // | "HS512" | HMAC using SHA-512 hash algorithm | | |
419 // | "RS256" | RSASSA using SHA-256 hash algorithm | | |
420 // | "RS384" | RSASSA using SHA-384 hash algorithm | | |
421 // | "RS512" | RSASSA using SHA-512 hash algorithm | | |
422 // +--------------+-------------------------------------------------------| | |
423 // | Key Management Algorithm | | |
424 // +--------------+-------------------------------------------------------+ | |
425 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | |
426 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | |
427 // | | (OAEP) [RFC3447], with the default parameters | | |
428 // | | specified by RFC3447 in Section A.2.1 | | |
429 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | | |
430 // | | [RFC3394] using 128 bit keys | | |
431 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | | |
432 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | | |
433 // | | 128 bit keys | | |
434 // | "A256GCM" | AES GCM using 256 bit keys | | |
435 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | | |
436 // | | padding [NIST.800-38A] [not yet part of JOSE] | | |
437 // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] | | |
438 // | "A384CBC" | AES CBC using 384 bit keys [not yet part of JOSE] | | |
439 // | "A512CBC" | AES CBC using 512 bit keys [not yet part of JOSE] | | |
440 // +--------------+-------------------------------------------------------+ | |
441 // | |
442 // kty-specific parameters | |
443 // The value of kty determines the type and content of the keying material | |
444 // carried in the JWK to be imported. Currently only two possibilities are | |
445 // supported: a raw key or an RSA public key. RSA private keys are not | |
446 // supported because typical applications seldom need to import a private key, | |
447 // and the large number of JWK parameters required to describe one. | |
448 // - kty == "oct" (symmetric or other raw key) | |
449 // +-------+--------------------------------------------------------------+ | |
450 // | "k" | Contains the value of the symmetric (or other single-valued) | | |
451 // | | key. It is represented as the base64url encoding of the | | |
452 // | | octet sequence containing the key value. | | |
453 // +-------+--------------------------------------------------------------+ | |
454 // - kty == "RSA" (RSA public key) | |
455 // +-------+--------------------------------------------------------------+ | |
456 // | "n" | Contains the modulus value for the RSA public key. It is | | |
457 // | | represented as the base64url encoding of the value's | | |
458 // | | unsigned big endian representation as an octet sequence. | | |
459 // +-------+--------------------------------------------------------------+ | |
460 // | "e" | Contains the exponent value for the RSA public key. It is | | |
461 // | | represented as the base64url encoding of the value's | | |
462 // | | unsigned big endian representation as an octet sequence. | | |
463 // +-------+--------------------------------------------------------------+ | |
464 // | |
465 // Conflict resolution | |
466 // The type, algorithm, extractable, and usage_mask input parameters may be | |
467 // different from similar values inside the JWK. Conflicts are resolved as | |
468 // follows: | |
469 // type: Deduce value from JWK contents only, ignore input value | |
470 // algorithm: Use JWK value if present, otherwise use input value | |
471 // extractable: If JWK value present, logical AND of the input and JWK values, | |
472 // otherwise use input value | |
473 // keyUsage: Use JWK value if present, otherwise use input value | |
Ryan Sleevi
2013/10/04 23:19:11
These are all things that should be in the spec be
padolph
2013/10/05 02:57:42
The other parameters are easy, but can you please
| |
474 | |
475 std::string jsonStr(key_data, key_data + key_data_size); | |
Ryan Sleevi
2013/10/04 23:19:11
json_str
However, you don't need to use std::stri
padolph
2013/10/05 02:57:42
Done.
| |
476 scoped_ptr<base::Value> value(base::JSONReader::Read(jsonStr)); | |
477 // Note, bare pointer dict_value is ok since it points into scoped value. | |
478 base::DictionaryValue* dict_value = NULL; | |
479 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) | |
480 return false; | |
481 | |
482 // JWK "kty". Exit early if this required JWK parameter is missing. | |
483 std::string jwk_kty_value; | |
484 if (!dict_value->GetString("kty", &jwk_kty_value)) | |
485 return false; | |
486 | |
487 // JWK "extractable" --> extractable parameter | |
488 bool jwk_extractable_value; | |
489 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) { | |
490 *extractable &= jwk_extractable_value; | |
491 } | |
492 | |
493 // JWK "alg" --> algorithm parameter | |
494 std::string jwk_alg_value; | |
495 if (dict_value->GetString("alg", &jwk_alg_value)) { | |
496 const StringIntMap::iterator pos = jwk_algorithm_map_.find(jwk_alg_value); | |
497 if (pos == jwk_algorithm_map_.end()) | |
498 return false; | |
499 const int jwk_algorithm_id = pos->second; | |
500 const unsigned short key_length_bits = | |
501 JwkAlgIdToKeyLengthBits(jwk_algorithm_id); | |
502 const WebKit::WebCryptoAlgorithmId webcrypto_algorithm_id = | |
503 JwkAlgIdToWebCryptoAlgId(jwk_algorithm_id); | |
504 switch (webcrypto_algorithm_id) { | |
505 case WebKit::WebCryptoAlgorithmIdHmac: | |
506 *algorithm = CreateHmacAlgorithm(key_length_bits); | |
507 break; | |
508 case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | |
509 *algorithm = CreateRsaSsaAlgorithm(key_length_bits); | |
510 break; | |
511 case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
512 *algorithm = CreateAlgorithm(webcrypto_algorithm_id); | |
513 break; | |
514 case WebKit::WebCryptoAlgorithmIdRsaOaep: | |
515 *algorithm = CreateRsaOaepAlgorithm(key_length_bits); | |
516 break; | |
517 case WebKit::WebCryptoAlgorithmIdAesGcm: | |
518 *algorithm = CreateAesGcmAlgorithm(key_length_bits); | |
519 break; | |
520 case WebKit::WebCryptoAlgorithmIdAesCbc: | |
521 *algorithm = CreateAesCbcAlgorithm(key_length_bits); | |
522 break; | |
523 default: | |
524 return false; | |
525 } | |
526 } | |
527 | |
528 // JWK "use" --> usage_mask parameter | |
529 std::string jwk_use_value; | |
530 if (dict_value->GetString("use", &jwk_use_value)) { | |
531 if (jwk_use_value == "enc") { | |
532 *usage_mask = | |
533 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt; | |
534 } else if (jwk_use_value == "sig") { | |
535 *usage_mask = | |
536 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; | |
537 } else if (jwk_use_value == "wrap") { | |
538 *usage_mask = | |
539 WebKit::WebCryptoKeyUsageWrapKey | WebKit::WebCryptoKeyUsageUnwrapKey; | |
540 } else { | |
541 return false; | |
542 } | |
543 } | |
544 | |
545 // JWK keying material --> ImportKeyInternal() | |
546 if (jwk_kty_value == "oct") { | |
547 std::string jwk_k_value_url64; | |
548 if (!dict_value->GetString("k", &jwk_k_value_url64)) | |
549 return false; | |
550 std::string jwk_k_value; | |
551 if (!Base64DecodeUrlSafe(jwk_k_value_url64, &jwk_k_value)) | |
552 return false; | |
553 const std::vector<uint8> data(jwk_k_value.begin(), jwk_k_value.end()); | |
554 if (!ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, | |
555 &data[0], | |
556 data.size(), | |
557 *algorithm, | |
558 *usage_mask, | |
559 handle, | |
560 type)) | |
561 return false; | |
562 } else if (jwk_kty_value == "RSA") { | |
563 // TODO(padolph): RSA public key | |
564 return false; | |
565 } else { | |
566 return false; | |
567 } | |
568 | |
569 return true; | |
570 } | |
571 | |
124 } // namespace content | 572 } // namespace content |
OLD | NEW |