IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / renderer / webcrypto / webcrypto_impl.cc
blob5d5a1415bb13cf28d5255cd384496e166831419d
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
3 // found in the LICENSE file.
5 #include "content/renderer/webcrypto/webcrypto_impl.h"
7 #include <algorithm>
8 #include <functional>
9 #include <map>
10 #include "base/json/json_reader.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/string_piece.h"
15 #include "base/values.h"
16 #include "content/renderer/webcrypto/webcrypto_util.h"
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
19 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
21 namespace content {
23 namespace {
25 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
26 // TODO(padolph): include all other asymmetric algorithms once they are
27 // defined, e.g. EC and DH.
28 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
29 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
30 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
33 // Binds a specific key length value to a compatible factory function.
34 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)(
35 unsigned short);
36 template <AlgFactoryFuncWithOneShortArg func, unsigned short key_length>
37 blink::WebCryptoAlgorithm BindAlgFactoryWithKeyLen() {
38 return func(key_length);
41 // Binds a WebCryptoAlgorithmId value to a compatible factory function.
42 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithWebCryptoAlgIdArg)(
43 blink::WebCryptoAlgorithmId);
44 template <AlgFactoryFuncWithWebCryptoAlgIdArg func,
45 blink::WebCryptoAlgorithmId algorithm_id>
46 blink::WebCryptoAlgorithm BindAlgFactoryAlgorithmId() {
47 return func(algorithm_id);
50 // Defines a map between a JWK 'alg' string ID and a corresponding Web Crypto
51 // factory function.
52 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncNoArgs)();
53 typedef std::map<std::string, AlgFactoryFuncNoArgs> JwkAlgFactoryMap;
55 class JwkAlgorithmFactoryMap {
56 public:
57 JwkAlgorithmFactoryMap() {
58 map_["HS256"] =
59 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId,
60 blink::WebCryptoAlgorithmIdSha256>;
61 map_["HS384"] =
62 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId,
63 blink::WebCryptoAlgorithmIdSha384>;
64 map_["HS512"] =
65 &BindAlgFactoryAlgorithmId<webcrypto::CreateHmacAlgorithmByHashId,
66 blink::WebCryptoAlgorithmIdSha512>;
67 map_["RS256"] =
68 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
69 blink::WebCryptoAlgorithmIdSha256>;
70 map_["RS384"] =
71 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
72 blink::WebCryptoAlgorithmIdSha384>;
73 map_["RS512"] =
74 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaSsaAlgorithm,
75 blink::WebCryptoAlgorithmIdSha512>;
76 map_["RSA1_5"] =
77 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
78 blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5>;
79 map_["RSA-OAEP"] =
80 &BindAlgFactoryAlgorithmId<webcrypto::CreateRsaOaepAlgorithm,
81 blink::WebCryptoAlgorithmIdSha1>;
82 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 128 yet
83 map_["A128KW"] = &blink::WebCryptoAlgorithm::createNull;
84 // TODO(padolph): The Web Crypto spec does not enumerate AES-KW 256 yet
85 map_["A256KW"] = &blink::WebCryptoAlgorithm::createNull;
86 map_["A128GCM"] =
87 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
88 blink::WebCryptoAlgorithmIdAesGcm>;
89 map_["A256GCM"] =
90 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
91 blink::WebCryptoAlgorithmIdAesGcm>;
92 map_["A128CBC"] =
93 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
94 blink::WebCryptoAlgorithmIdAesCbc>;
95 map_["A192CBC"] =
96 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
97 blink::WebCryptoAlgorithmIdAesCbc>;
98 map_["A256CBC"] =
99 &BindAlgFactoryAlgorithmId<webcrypto::CreateAlgorithm,
100 blink::WebCryptoAlgorithmIdAesCbc>;
103 blink::WebCryptoAlgorithm CreateAlgorithmFromName(const std::string& alg_id)
104 const {
105 const JwkAlgFactoryMap::const_iterator pos = map_.find(alg_id);
106 if (pos == map_.end())
107 return blink::WebCryptoAlgorithm::createNull();
108 return pos->second();
111 private:
112 JwkAlgFactoryMap map_;
115 base::LazyInstance<JwkAlgorithmFactoryMap> jwk_alg_factory =
116 LAZY_INSTANCE_INITIALIZER;
118 bool WebCryptoAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1,
119 const blink::WebCryptoAlgorithm& alg2) {
120 DCHECK(!alg1.isNull());
121 DCHECK(!alg2.isNull());
122 if (alg1.id() != alg2.id())
123 return false;
124 switch (alg1.id()) {
125 case blink::WebCryptoAlgorithmIdHmac:
126 case blink::WebCryptoAlgorithmIdRsaOaep:
127 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
128 if (WebCryptoAlgorithmsConsistent(
129 webcrypto::GetInnerHashAlgorithm(alg1),
130 webcrypto::GetInnerHashAlgorithm(alg2))) {
131 return true;
133 break;
134 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
135 case blink::WebCryptoAlgorithmIdSha1:
136 case blink::WebCryptoAlgorithmIdSha224:
137 case blink::WebCryptoAlgorithmIdSha256:
138 case blink::WebCryptoAlgorithmIdSha384:
139 case blink::WebCryptoAlgorithmIdSha512:
140 case blink::WebCryptoAlgorithmIdAesCbc:
141 case blink::WebCryptoAlgorithmIdAesGcm:
142 case blink::WebCryptoAlgorithmIdAesCtr:
143 return true;
144 default:
145 NOTREACHED(); // Not a supported algorithm.
146 break;
148 return false;
151 bool GetDecodedUrl64ValueByKey(
152 const base::DictionaryValue& dict,
153 const std::string& key,
154 std::string* decoded) {
155 std::string value_url64;
156 if (!dict.GetString(key, &value_url64) ||
157 !webcrypto::Base64DecodeUrlSafe(value_url64, decoded) ||
158 !decoded->size()) {
159 return false;
161 return true;
164 } // namespace
166 WebCryptoImpl::WebCryptoImpl() {
167 Init();
170 void WebCryptoImpl::encrypt(
171 const blink::WebCryptoAlgorithm& algorithm,
172 const blink::WebCryptoKey& key,
173 const unsigned char* data,
174 unsigned data_size,
175 blink::WebCryptoResult result) {
176 DCHECK(!algorithm.isNull());
177 blink::WebArrayBuffer buffer;
178 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) {
179 result.completeWithError();
180 } else {
181 result.completeWithBuffer(buffer);
185 void WebCryptoImpl::decrypt(
186 const blink::WebCryptoAlgorithm& algorithm,
187 const blink::WebCryptoKey& key,
188 const unsigned char* data,
189 unsigned data_size,
190 blink::WebCryptoResult result) {
191 DCHECK(!algorithm.isNull());
192 blink::WebArrayBuffer buffer;
193 if (!DecryptInternal(algorithm, key, data, data_size, &buffer)) {
194 result.completeWithError();
195 } else {
196 result.completeWithBuffer(buffer);
200 void WebCryptoImpl::digest(
201 const blink::WebCryptoAlgorithm& algorithm,
202 const unsigned char* data,
203 unsigned data_size,
204 blink::WebCryptoResult result) {
205 DCHECK(!algorithm.isNull());
206 blink::WebArrayBuffer buffer;
207 if (!DigestInternal(algorithm, data, data_size, &buffer)) {
208 result.completeWithError();
209 } else {
210 result.completeWithBuffer(buffer);
214 void WebCryptoImpl::generateKey(
215 const blink::WebCryptoAlgorithm& algorithm,
216 bool extractable,
217 blink::WebCryptoKeyUsageMask usage_mask,
218 blink::WebCryptoResult result) {
219 DCHECK(!algorithm.isNull());
220 if (IsAlgorithmAsymmetric(algorithm)) {
221 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
222 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
223 if (!GenerateKeyPairInternal(
224 algorithm, extractable, usage_mask, &public_key, &private_key)) {
225 result.completeWithError();
226 } else {
227 DCHECK(public_key.handle());
228 DCHECK(private_key.handle());
229 DCHECK_EQ(algorithm.id(), public_key.algorithm().id());
230 DCHECK_EQ(algorithm.id(), private_key.algorithm().id());
231 DCHECK_EQ(true, public_key.extractable());
232 DCHECK_EQ(extractable, private_key.extractable());
233 DCHECK_EQ(usage_mask, public_key.usages());
234 DCHECK_EQ(usage_mask, private_key.usages());
235 result.completeWithKeyPair(public_key, private_key);
237 } else {
238 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
239 if (!GenerateKeyInternal(algorithm, extractable, usage_mask, &key)) {
240 result.completeWithError();
241 } else {
242 DCHECK(key.handle());
243 DCHECK_EQ(algorithm.id(), key.algorithm().id());
244 DCHECK_EQ(extractable, key.extractable());
245 DCHECK_EQ(usage_mask, key.usages());
246 result.completeWithKey(key);
251 void WebCryptoImpl::importKey(
252 blink::WebCryptoKeyFormat format,
253 const unsigned char* key_data,
254 unsigned key_data_size,
255 const blink::WebCryptoAlgorithm& algorithm_or_null,
256 bool extractable,
257 blink::WebCryptoKeyUsageMask usage_mask,
258 blink::WebCryptoResult result) {
259 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
260 if (format == blink::WebCryptoKeyFormatJwk) {
261 if (!ImportKeyJwk(key_data,
262 key_data_size,
263 algorithm_or_null,
264 extractable,
265 usage_mask,
266 &key)) {
267 result.completeWithError();
268 return;
270 } else {
271 if (!ImportKeyInternal(format,
272 key_data,
273 key_data_size,
274 algorithm_or_null,
275 extractable,
276 usage_mask,
277 &key)) {
278 result.completeWithError();
279 return;
282 DCHECK(key.handle());
283 DCHECK(!key.algorithm().isNull());
284 DCHECK_EQ(extractable, key.extractable());
285 result.completeWithKey(key);
288 void WebCryptoImpl::exportKey(
289 blink::WebCryptoKeyFormat format,
290 const blink::WebCryptoKey& key,
291 blink::WebCryptoResult result) {
292 blink::WebArrayBuffer buffer;
293 if (!ExportKeyInternal(format, key, &buffer)) {
294 result.completeWithError();
295 return;
297 result.completeWithBuffer(buffer);
300 void WebCryptoImpl::sign(
301 const blink::WebCryptoAlgorithm& algorithm,
302 const blink::WebCryptoKey& key,
303 const unsigned char* data,
304 unsigned data_size,
305 blink::WebCryptoResult result) {
306 DCHECK(!algorithm.isNull());
307 blink::WebArrayBuffer buffer;
308 if (!SignInternal(algorithm, key, data, data_size, &buffer)) {
309 result.completeWithError();
310 } else {
311 result.completeWithBuffer(buffer);
315 void WebCryptoImpl::verifySignature(
316 const blink::WebCryptoAlgorithm& algorithm,
317 const blink::WebCryptoKey& key,
318 const unsigned char* signature,
319 unsigned signature_size,
320 const unsigned char* data,
321 unsigned data_size,
322 blink::WebCryptoResult result) {
323 DCHECK(!algorithm.isNull());
324 bool signature_match = false;
325 if (!VerifySignatureInternal(algorithm,
326 key,
327 signature,
328 signature_size,
329 data,
330 data_size,
331 &signature_match)) {
332 result.completeWithError();
333 } else {
334 result.completeWithBoolean(signature_match);
338 bool WebCryptoImpl::ImportKeyJwk(
339 const unsigned char* key_data,
340 unsigned key_data_size,
341 const blink::WebCryptoAlgorithm& algorithm_or_null,
342 bool extractable,
343 blink::WebCryptoKeyUsageMask usage_mask,
344 blink::WebCryptoKey* key) {
346 // The goal of this method is to extract key material and meta data from the
347 // incoming JWK, combine them with the input parameters, and ultimately import
348 // a Web Crypto Key.
350 // JSON Web Key Format (JWK)
351 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-16
352 // TODO(padolph): Not all possible values are handled by this code right now
354 // A JWK is a simple JSON dictionary with the following entries
355 // - "kty" (Key Type) Parameter, REQUIRED
356 // - <kty-specific parameters, see below>, REQUIRED
357 // - "use" (Key Use) Parameter, OPTIONAL
358 // - "alg" (Algorithm) Parameter, OPTIONAL
359 // - "extractable" (Key Exportability), OPTIONAL [NOTE: not yet part of JOSE,
360 // see https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796]
361 // (all other entries are ignored)
363 // OPTIONAL here means that this code does not require the entry to be present
364 // in the incoming JWK, because the method input parameters contain similar
365 // information. If the optional JWK entry is present, it will be validated
366 // against the corresponding input parameter for consistency and combined with
367 // it according to rules defined below. A special case is that the method
368 // input parameter 'algorithm' is also optional. If it is null, the JWK 'alg'
369 // value (if present) is used as a fallback.
371 // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK
372 // values are parsed out and combined with the method input parameters to
373 // build a Web Crypto Key:
374 // Web Crypto Key type <-- (deduced)
375 // Web Crypto Key extractable <-- JWK extractable + input extractable
376 // Web Crypto Key algorithm <-- JWK alg + input algorithm
377 // Web Crypto Key keyUsage <-- JWK use + input usage_mask
378 // Web Crypto Key keying material <-- kty-specific parameters
380 // Values for each JWK entry are case-sensitive and defined in
381 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16.
382 // Note that not all values specified by JOSE are handled by this code. Only
383 // handled values are listed.
384 // - kty (Key Type)
385 // +-------+--------------------------------------------------------------+
386 // | "RSA" | RSA [RFC3447] |
387 // | "oct" | Octet sequence (used to represent symmetric keys) |
388 // +-------+--------------------------------------------------------------+
389 // - use (Key Use)
390 // +-------+--------------------------------------------------------------+
391 // | "enc" | encrypt and decrypt operations |
392 // | "sig" | sign and verify (MAC) operations |
393 // | "wrap"| key wrap and unwrap [not yet part of JOSE] |
394 // +-------+--------------------------------------------------------------+
395 // - extractable (Key Exportability)
396 // +-------+--------------------------------------------------------------+
397 // | true | Key may be exported from the trusted environment |
398 // | false | Key cannot exit the trusted environment |
399 // +-------+--------------------------------------------------------------+
400 // - alg (Algorithm)
401 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-16
402 // +--------------+-------------------------------------------------------+
403 // | Digital Signature or MAC Algorithm |
404 // +--------------+-------------------------------------------------------+
405 // | "HS256" | HMAC using SHA-256 hash algorithm |
406 // | "HS384" | HMAC using SHA-384 hash algorithm |
407 // | "HS512" | HMAC using SHA-512 hash algorithm |
408 // | "RS256" | RSASSA using SHA-256 hash algorithm |
409 // | "RS384" | RSASSA using SHA-384 hash algorithm |
410 // | "RS512" | RSASSA using SHA-512 hash algorithm |
411 // +--------------+-------------------------------------------------------|
412 // | Key Management Algorithm |
413 // +--------------+-------------------------------------------------------+
414 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] |
415 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding |
416 // | | (OAEP) [RFC3447], with the default parameters |
417 // | | specified by RFC3447 in Section A.2.1 |
418 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm |
419 // | | [RFC3394] using 128 bit keys |
420 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys |
421 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using |
422 // | | 128 bit keys |
423 // | "A256GCM" | AES GCM using 256 bit keys |
424 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 |
425 // | | padding [NIST.800-38A] [not yet part of JOSE, see |
426 // | | https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796 |
427 // | "A192CBC" | AES CBC using 192 bit keys [not yet part of JOSE] |
428 // | "A256CBC" | AES CBC using 256 bit keys [not yet part of JOSE] |
429 // +--------------+-------------------------------------------------------+
431 // kty-specific parameters
432 // The value of kty determines the type and content of the keying material
433 // carried in the JWK to be imported. Currently only two possibilities are
434 // supported: a raw key or an RSA public key. RSA private keys are not
435 // supported because typical applications seldom need to import a private key,
436 // and the large number of JWK parameters required to describe one.
437 // - kty == "oct" (symmetric or other raw key)
438 // +-------+--------------------------------------------------------------+
439 // | "k" | Contains the value of the symmetric (or other single-valued) |
440 // | | key. It is represented as the base64url encoding of the |
441 // | | octet sequence containing the key value. |
442 // +-------+--------------------------------------------------------------+
443 // - kty == "RSA" (RSA public key)
444 // +-------+--------------------------------------------------------------+
445 // | "n" | Contains the modulus value for the RSA public key. It is |
446 // | | represented as the base64url encoding of the value's |
447 // | | unsigned big endian representation as an octet sequence. |
448 // +-------+--------------------------------------------------------------+
449 // | "e" | Contains the exponent value for the RSA public key. It is |
450 // | | represented as the base64url encoding of the value's |
451 // | | unsigned big endian representation as an octet sequence. |
452 // +-------+--------------------------------------------------------------+
454 // Consistency and conflict resolution
455 // The 'algorithm_or_null', 'extractable', and 'usage_mask' input parameters
456 // may be different than the corresponding values inside the JWK. The Web
457 // Crypto spec says that if a JWK value is present but is inconsistent with
458 // the input value, it is an error and the operation must fail. If no
459 // inconsistency is found, the input and JWK values are combined as follows:
461 // algorithm
462 // If an algorithm is provided by both the input parameter and the JWK,
463 // consistency between the two is based only on algorithm ID's (including an
464 // inner hash algorithm if present). In this case if the consistency
465 // check is passed, the input algorithm is used. If only one of either the
466 // input algorithm and JWK alg is provided, it is used as the final
467 // algorithm.
469 // extractable
470 // If the JWK extractable is true but the input parameter is false, make the
471 // Web Crypto Key non-extractable. Conversely, if the JWK extractable is
472 // false but the input parameter is true, it is an inconsistency. If both
473 // are true or both are false, use that value.
475 // usage_mask
476 // The input usage_mask must be a strict subset of the interpreted JWK use
477 // value, else it is judged inconsistent. In all cases the input usage_mask
478 // is used as the final usage_mask.
481 if (!key_data_size)
482 return false;
483 DCHECK(key);
485 // Parse the incoming JWK JSON.
486 base::StringPiece json_string(reinterpret_cast<const char*>(key_data),
487 key_data_size);
488 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
489 // Note, bare pointer dict_value is ok since it points into scoped value.
490 base::DictionaryValue* dict_value = NULL;
491 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
492 return false;
494 // JWK "kty". Exit early if this required JWK parameter is missing.
495 std::string jwk_kty_value;
496 if (!dict_value->GetString("kty", &jwk_kty_value))
497 return false;
499 // JWK "extractable" (optional) --> extractable parameter
501 bool jwk_extractable_value;
502 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) {
503 if (!jwk_extractable_value && extractable)
504 return false;
505 extractable = extractable && jwk_extractable_value;
509 // JWK "alg" (optional) --> algorithm parameter
510 // Note: input algorithm is also optional, so we have six cases to handle.
511 // 1. JWK alg present but unrecognized: error
512 // 2. JWK alg valid AND input algorithm isNull: use JWK value
513 // 3. JWK alg valid AND input algorithm specified, but JWK value
514 // inconsistent with input: error
515 // 4. JWK alg valid AND input algorithm specified, both consistent: use
516 // input value (because it has potentially more details)
517 // 5. JWK alg missing AND input algorithm isNull: error
518 // 6. JWK alg missing AND input algorithm specified: use input value
519 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull();
520 std::string jwk_alg_value;
521 if (dict_value->GetString("alg", &jwk_alg_value)) {
522 // JWK alg present
524 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can
525 // only be from the RSA family.
527 const blink::WebCryptoAlgorithm jwk_algorithm =
528 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value);
529 if (jwk_algorithm.isNull()) {
530 // JWK alg unrecognized
531 return false; // case 1
533 // JWK alg valid
534 if (algorithm_or_null.isNull()) {
535 // input algorithm not specified
536 algorithm = jwk_algorithm; // case 2
537 } else {
538 // input algorithm specified
539 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null))
540 return false; // case 3
541 algorithm = algorithm_or_null; // case 4
543 } else {
544 // JWK alg missing
545 if (algorithm_or_null.isNull())
546 return false; // case 5
547 algorithm = algorithm_or_null; // case 6
549 DCHECK(!algorithm.isNull());
551 // JWK "use" (optional) --> usage_mask parameter
552 std::string jwk_use_value;
553 if (dict_value->GetString("use", &jwk_use_value)) {
554 blink::WebCryptoKeyUsageMask jwk_usage_mask = 0;
555 if (jwk_use_value == "enc") {
556 jwk_usage_mask =
557 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
558 } else if (jwk_use_value == "sig") {
559 jwk_usage_mask =
560 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
561 } else if (jwk_use_value == "wrap") {
562 jwk_usage_mask =
563 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey;
564 } else {
565 return false;
567 if ((jwk_usage_mask & usage_mask) != usage_mask) {
568 // A usage_mask must be a subset of jwk_usage_mask.
569 return false;
573 // JWK keying material --> ImportKeyInternal()
574 if (jwk_kty_value == "oct") {
576 std::string jwk_k_value;
577 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value))
578 return false;
580 // TODO(padolph): Some JWK alg ID's embed information about the key length
581 // in the alg ID string. For example "A128" implies the JWK carries 128 bits
582 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits
583 // of key material. For such keys validate the actual key length against the
584 // value in the ID.
586 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
587 reinterpret_cast<const uint8*>(jwk_k_value.data()),
588 jwk_k_value.size(),
589 algorithm,
590 extractable,
591 usage_mask,
592 key);
593 } else if (jwk_kty_value == "RSA") {
595 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
596 // in the JWK, while an RSA private key must have those, plus at least a "d"
597 // (private exponent) entry.
598 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
599 // section 6.3.
601 // RSA private key import is not currently supported, so fail here if a "d"
602 // entry is found.
603 // TODO(padolph): Support RSA private key import.
604 if (dict_value->HasKey("d"))
605 return false;
607 std::string jwk_n_value;
608 if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value))
609 return false;
610 std::string jwk_e_value;
611 if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value))
612 return false;
614 return ImportRsaPublicKeyInternal(
615 reinterpret_cast<const uint8*>(jwk_n_value.data()),
616 jwk_n_value.size(),
617 reinterpret_cast<const uint8*>(jwk_e_value.data()),
618 jwk_e_value.size(),
619 algorithm,
620 extractable,
621 usage_mask,
622 key);
624 } else {
625 return false;
628 return true;
631 } // namespace content