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/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 blink::WebCryptoAlgorithmIdSha1>); | 85 blink::WebCryptoAlgorithmIdSha1>); |
86 alg_to_info_["HS256"] = | 86 alg_to_info_["HS256"] = |
87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
88 blink::WebCryptoAlgorithmIdSha256>); | 88 blink::WebCryptoAlgorithmIdSha256>); |
89 alg_to_info_["HS384"] = | 89 alg_to_info_["HS384"] = |
90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
91 blink::WebCryptoAlgorithmIdSha384>); | 91 blink::WebCryptoAlgorithmIdSha384>); |
92 alg_to_info_["HS512"] = | 92 alg_to_info_["HS512"] = |
93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, | 93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, |
94 blink::WebCryptoAlgorithmIdSha512>); | 94 blink::WebCryptoAlgorithmIdSha512>); |
95 alg_to_info_["RS1"] = | |
96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | |
97 blink::WebCryptoAlgorithmIdSha1>); | |
95 alg_to_info_["RS256"] = | 98 alg_to_info_["RS256"] = |
96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
97 blink::WebCryptoAlgorithmIdSha256>); | 100 blink::WebCryptoAlgorithmIdSha256>); |
98 alg_to_info_["RS384"] = | 101 alg_to_info_["RS384"] = |
99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
100 blink::WebCryptoAlgorithmIdSha384>); | 103 blink::WebCryptoAlgorithmIdSha384>); |
101 alg_to_info_["RS512"] = | 104 alg_to_info_["RS512"] = |
102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, | 105 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, |
103 blink::WebCryptoAlgorithmIdSha512>); | 106 blink::WebCryptoAlgorithmIdSha512>); |
104 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( | 107 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 // base64url encoding of the raw key. | 291 // base64url encoding of the raw key. |
289 DCHECK(!raw_key.isNull()); | 292 DCHECK(!raw_key.isNull()); |
290 DCHECK(raw_key.data()); | 293 DCHECK(raw_key.data()); |
291 DCHECK(raw_key.byteLength()); | 294 DCHECK(raw_key.byteLength()); |
292 unsigned int key_length_bytes = raw_key.byteLength(); | 295 unsigned int key_length_bytes = raw_key.byteLength(); |
293 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()), | 296 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()), |
294 key_length_bytes); | 297 key_length_bytes); |
295 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); | 298 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); |
296 } | 299 } |
297 | 300 |
301 // Writes an RSA public key to a JWK dictionary | |
302 void WriteRsaPublicKey(const blink::WebArrayBuffer& modulus, | |
303 const blink::WebArrayBuffer& public_exponent, | |
304 base::DictionaryValue* jwk_dict) { | |
305 DCHECK(jwk_dict); | |
306 jwk_dict->SetString("kty", "RSA"); | |
307 | |
308 DCHECK(!modulus.isNull()); | |
309 DCHECK(modulus.data()); | |
310 DCHECK(modulus.byteLength()); | |
311 const unsigned int modulus_length_bytes = modulus.byteLength(); | |
312 const base::StringPiece modulus_str(static_cast<const char*>(modulus.data()), | |
eroman
2014/03/21 02:30:51
There are now 3 places in the code which do this i
padolph
2014/03/24 04:28:28
Done.
| |
313 modulus_length_bytes); | |
314 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus_str)); | |
315 | |
316 DCHECK(!public_exponent.isNull()); | |
eroman
2014/03/21 02:30:51
my preference is to put all input dchecks at the t
padolph
2014/03/24 04:28:28
Done.
| |
317 DCHECK(public_exponent.data()); | |
318 DCHECK(public_exponent.byteLength()); | |
319 const unsigned int public_exponent_length_bytes = | |
320 public_exponent.byteLength(); | |
321 const base::StringPiece public_exponent_str( | |
322 static_cast<const char*>(public_exponent.data()), | |
323 public_exponent_length_bytes); | |
324 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent_str)); | |
325 } | |
326 | |
298 // Writes a Web Crypto usage mask to a JWK dictionary. | 327 // Writes a Web Crypto usage mask to a JWK dictionary. |
299 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, | 328 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, |
300 base::DictionaryValue* jwk_dict) { | 329 base::DictionaryValue* jwk_dict) { |
301 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); | 330 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); |
302 } | 331 } |
303 | 332 |
304 // Writes a Web Crypto extractable value to a JWK dictionary. | 333 // Writes a Web Crypto extractable value to a JWK dictionary. |
305 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { | 334 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { |
306 jwk_dict->SetBoolean("ext", extractable); | 335 jwk_dict->SetBoolean("ext", extractable); |
307 } | 336 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 case blink::WebCryptoAlgorithmIdSha512: | 392 case blink::WebCryptoAlgorithmIdSha512: |
364 jwk_dict->SetString("alg", "HS512"); | 393 jwk_dict->SetString("alg", "HS512"); |
365 break; | 394 break; |
366 default: | 395 default: |
367 NOTREACHED(); | 396 NOTREACHED(); |
368 return Status::ErrorUnexpected(); | 397 return Status::ErrorUnexpected(); |
369 } | 398 } |
370 break; | 399 break; |
371 } | 400 } |
372 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | 401 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
402 switch (algorithm.id()) { | |
403 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
404 jwk_dict->SetString("alg", "RSA1_5"); | |
405 break; | |
406 case blink::WebCryptoAlgorithmIdRsaOaep: | |
eroman
2014/03/21 02:30:51
I don't believe this is correct.
In WebCrypto RSA
padolph
2014/03/24 04:28:28
Done.
| |
407 jwk_dict->SetString("alg", "RSA-OAEP"); | |
408 break; | |
409 default: | |
410 NOTREACHED(); | |
411 return Status::ErrorUnexpected(); | |
412 } | |
413 break; | |
373 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | 414 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
374 // TODO(padolph): Handle RSA key | 415 switch (algorithm.rsaHashedParams()->hash().id()) { |
375 return Status::ErrorUnsupported(); | 416 case blink::WebCryptoAlgorithmIdSha1: |
417 jwk_dict->SetString("alg", "RS1"); | |
418 break; | |
419 case blink::WebCryptoAlgorithmIdSha256: | |
420 jwk_dict->SetString("alg", "RS256"); | |
421 break; | |
422 case blink::WebCryptoAlgorithmIdSha384: | |
423 jwk_dict->SetString("alg", "RS384"); | |
424 break; | |
425 case blink::WebCryptoAlgorithmIdSha512: | |
426 jwk_dict->SetString("alg", "RS512"); | |
427 break; | |
428 default: | |
429 NOTREACHED(); | |
430 return Status::ErrorUnexpected(); | |
431 } | |
432 break; | |
376 default: | 433 default: |
377 return Status::ErrorUnsupported(); | 434 return Status::ErrorUnsupported(); |
378 } | 435 } |
379 return Status::Success(); | 436 return Status::Success(); |
380 } | 437 } |
381 | 438 |
439 bool IsRsaPublicKey(const blink::WebCryptoKey& key) { | |
440 if (key.type() != blink::WebCryptoKeyTypePublic) | |
441 return false; | |
442 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); | |
443 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | |
444 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | |
445 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; | |
446 } | |
447 | |
448 // TODO(padolph): This function is duplicated in shared_crypto.cc | |
449 Status ToPlatformPublicKey(const blink::WebCryptoKey& key, | |
450 platform::PublicKey** out) { | |
451 *out = static_cast<platform::Key*>(key.handle())->AsPublicKey(); | |
452 if (!*out) | |
453 return Status::ErrorUnexpectedKeyType(); | |
454 return Status::Success(); | |
455 } | |
456 | |
382 } // namespace | 457 } // namespace |
383 | 458 |
384 Status ImportKeyJwk(const CryptoData& key_data, | 459 Status ImportKeyJwk(const CryptoData& key_data, |
385 const blink::WebCryptoAlgorithm& algorithm, | 460 const blink::WebCryptoAlgorithm& algorithm, |
386 bool extractable, | 461 bool extractable, |
387 blink::WebCryptoKeyUsageMask usage_mask, | 462 blink::WebCryptoKeyUsageMask usage_mask, |
388 blink::WebCryptoKey* key) { | 463 blink::WebCryptoKey* key) { |
389 // TODO(padolph): Generalize this comment to include export, and move to top | 464 // TODO(padolph): Generalize this comment to include export, and move to top |
390 // of file. | 465 // of file. |
391 | 466 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 // | 546 // |
472 // - alg (Algorithm) | 547 // - alg (Algorithm) |
473 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 | 548 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 |
474 // +--------------+-------------------------------------------------------+ | 549 // +--------------+-------------------------------------------------------+ |
475 // | Digital Signature or MAC Algorithm | | 550 // | Digital Signature or MAC Algorithm | |
476 // +--------------+-------------------------------------------------------+ | 551 // +--------------+-------------------------------------------------------+ |
477 // | "HS1" | HMAC using SHA-1 hash algorithm | | 552 // | "HS1" | HMAC using SHA-1 hash algorithm | |
478 // | "HS256" | HMAC using SHA-256 hash algorithm | | 553 // | "HS256" | HMAC using SHA-256 hash algorithm | |
479 // | "HS384" | HMAC using SHA-384 hash algorithm | | 554 // | "HS384" | HMAC using SHA-384 hash algorithm | |
480 // | "HS512" | HMAC using SHA-512 hash algorithm | | 555 // | "HS512" | HMAC using SHA-512 hash algorithm | |
556 // | "RS1" | RSASSA using SHA-1 hash algorithm | |
481 // | "RS256" | RSASSA using SHA-256 hash algorithm | | 557 // | "RS256" | RSASSA using SHA-256 hash algorithm | |
482 // | "RS384" | RSASSA using SHA-384 hash algorithm | | 558 // | "RS384" | RSASSA using SHA-384 hash algorithm | |
483 // | "RS512" | RSASSA using SHA-512 hash algorithm | | 559 // | "RS512" | RSASSA using SHA-512 hash algorithm | |
484 // +--------------+-------------------------------------------------------| | 560 // +--------------+-------------------------------------------------------| |
485 // | Key Management Algorithm | | 561 // | Key Management Algorithm | |
486 // +--------------+-------------------------------------------------------+ | 562 // +--------------+-------------------------------------------------------+ |
487 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | 563 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | |
488 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | 564 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | |
489 // | | (OAEP) [RFC3447], with the default parameters | | 565 // | | (OAEP) [RFC3447], with the default parameters | |
490 // | | specified by RFC3447 in Section A.2.1 | | 566 // | | specified by RFC3447 in Section A.2.1 | |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
707 CryptoData(jwk_e_value), | 783 CryptoData(jwk_e_value), |
708 key); | 784 key); |
709 | 785 |
710 } | 786 } |
711 | 787 |
712 return Status::ErrorJwkUnrecognizedKty(); | 788 return Status::ErrorJwkUnrecognizedKty(); |
713 } | 789 } |
714 | 790 |
715 Status ExportKeyJwk(const blink::WebCryptoKey& key, | 791 Status ExportKeyJwk(const blink::WebCryptoKey& key, |
716 blink::WebArrayBuffer* buffer) { | 792 blink::WebArrayBuffer* buffer) { |
793 DCHECK(key.extractable()); | |
717 base::DictionaryValue jwk_dict; | 794 base::DictionaryValue jwk_dict; |
718 Status status = Status::Error(); | 795 Status status = Status::Error(); |
719 blink::WebArrayBuffer exported_key; | |
720 | 796 |
721 if (key.type() == blink::WebCryptoKeyTypeSecret) { | 797 unsigned int key_length_bytes = 0; |
722 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); | 798 switch (key.type()) { |
723 if (status.IsError()) | 799 case blink::WebCryptoKeyTypeSecret: { |
724 return status; | 800 blink::WebArrayBuffer exported_key; |
725 WriteSecretKey(exported_key, &jwk_dict); | 801 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
726 } else { | 802 if (status.IsError()) |
727 // TODO(padolph): Handle asymmetric keys, at least the public key. | 803 return status; |
728 return Status::ErrorUnsupported(); | 804 key_length_bytes = exported_key.byteLength(); |
805 WriteSecretKey(exported_key, &jwk_dict); | |
806 break; | |
807 } | |
808 case blink::WebCryptoKeyTypePublic: { | |
809 // Currently only RSA public key export is supported. | |
810 if (!IsRsaPublicKey(key)) | |
811 return Status::ErrorUnsupported(); | |
812 platform::PublicKey* public_key; | |
813 status = ToPlatformPublicKey(key, &public_key); | |
814 if (status.IsError()) | |
815 return status; | |
816 blink::WebArrayBuffer modulus, public_exponent; | |
817 status = | |
818 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); | |
819 if (status.IsError()) | |
820 return status; | |
821 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); | |
822 break; | |
823 } | |
824 case blink::WebCryptoKeyTypePrivate: // TODO(padolph) | |
825 default: | |
826 return Status::ErrorUnsupported(); | |
729 } | 827 } |
730 | 828 |
731 WriteKeyOps(key.usages(), &jwk_dict); | 829 WriteKeyOps(key.usages(), &jwk_dict); |
732 WriteExt(key.extractable(), &jwk_dict); | 830 WriteExt(key.extractable(), &jwk_dict); |
733 status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict); | 831 status = WriteAlg(key.algorithm(), key_length_bytes, &jwk_dict); |
734 if (status.IsError()) | 832 if (status.IsError()) |
735 return status; | 833 return status; |
736 | 834 |
737 std::string json; | 835 std::string json; |
738 base::JSONWriter::Write(&jwk_dict, &json); | 836 base::JSONWriter::Write(&jwk_dict, &json); |
739 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), | 837 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), |
740 json.size()); | 838 json.size()); |
741 return Status::Success(); | 839 return Status::Success(); |
742 } | 840 } |
743 | 841 |
744 } // namespace webcrypto | 842 } // namespace webcrypto |
745 | 843 |
746 } // namespace content | 844 } // namespace content |
OLD | NEW |