Chromium Code Reviews| 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 |