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 std::vector<uint8>& modulus, | |
| 303 const std::vector<uint8>& public_exponent, | |
| 304 base::DictionaryValue* jwk_dict) { | |
| 305 DCHECK(jwk_dict); | |
| 306 DCHECK(modulus.size()); | |
| 307 DCHECK(public_exponent.size()); | |
| 308 jwk_dict->SetString("kty", "RSA"); | |
| 309 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus)); | |
| 310 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent)); | |
| 311 } | |
| 312 | |
| 298 // Writes a Web Crypto usage mask to a JWK dictionary. | 313 // Writes a Web Crypto usage mask to a JWK dictionary. |
| 299 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, | 314 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, |
| 300 base::DictionaryValue* jwk_dict) { | 315 base::DictionaryValue* jwk_dict) { |
| 301 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); | 316 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); |
| 302 } | 317 } |
| 303 | 318 |
| 304 // Writes a Web Crypto extractable value to a JWK dictionary. | 319 // Writes a Web Crypto extractable value to a JWK dictionary. |
| 305 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { | 320 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { |
| 306 jwk_dict->SetBoolean("ext", extractable); | 321 jwk_dict->SetBoolean("ext", extractable); |
| 307 } | 322 } |
| 308 | 323 |
| 309 // Writes a Web Crypto algorithm to a JWK dictionary. | 324 // Writes a Web Crypto algorithm to a JWK dictionary. |
| 310 Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm, | 325 Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm, |
| 311 unsigned int raw_key_length_bytes, | 326 unsigned int raw_key_length_bytes, |
|
eroman
2014/03/24 22:05:51
Please delete this parameter (makes the caller ugl
padolph
2014/03/25 01:10:28
Done.
| |
| 312 base::DictionaryValue* jwk_dict) { | 327 base::DictionaryValue* jwk_dict) { |
| 313 switch (algorithm.paramsType()) { | 328 switch (algorithm.paramsType()) { |
| 314 case blink::WebCryptoKeyAlgorithmParamsTypeAes: { | 329 case blink::WebCryptoKeyAlgorithmParamsTypeAes: { |
| 315 const char* aes_prefix = ""; | 330 const char* aes_prefix = ""; |
| 316 switch (raw_key_length_bytes) { | 331 switch (raw_key_length_bytes) { |
|
eroman
2014/03/24 22:05:51
Instead we can use:
algorithm.aesParams()->length
padolph
2014/03/25 01:10:28
Done.
| |
| 317 case 16: | 332 case 16: |
| 318 aes_prefix = "A128"; | 333 aes_prefix = "A128"; |
| 319 break; | 334 break; |
| 320 case 24: | 335 case 24: |
| 321 aes_prefix = "A192"; | 336 aes_prefix = "A192"; |
| 322 break; | 337 break; |
| 323 case 32: | 338 case 32: |
| 324 aes_prefix = "A256"; | 339 aes_prefix = "A256"; |
| 325 break; | 340 break; |
| 326 default: | 341 default: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 363 case blink::WebCryptoAlgorithmIdSha512: | 378 case blink::WebCryptoAlgorithmIdSha512: |
| 364 jwk_dict->SetString("alg", "HS512"); | 379 jwk_dict->SetString("alg", "HS512"); |
| 365 break; | 380 break; |
| 366 default: | 381 default: |
| 367 NOTREACHED(); | 382 NOTREACHED(); |
| 368 return Status::ErrorUnexpected(); | 383 return Status::ErrorUnexpected(); |
| 369 } | 384 } |
| 370 break; | 385 break; |
| 371 } | 386 } |
| 372 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | 387 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
| 388 switch (algorithm.id()) { | |
| 389 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
| 390 jwk_dict->SetString("alg", "RSA1_5"); | |
| 391 break; | |
| 392 default: | |
| 393 NOTREACHED(); | |
| 394 return Status::ErrorUnexpected(); | |
| 395 } | |
| 396 break; | |
| 373 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | 397 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
| 374 // TODO(padolph): Handle RSA key | 398 switch (algorithm.rsaHashedParams()->hash().id()) { |
| 375 return Status::ErrorUnsupported(); | 399 case blink::WebCryptoAlgorithmIdRsaOaep: |
| 400 jwk_dict->SetString("alg", "RSA-OAEP"); | |
| 401 break; | |
| 402 case blink::WebCryptoAlgorithmIdSha1: | |
| 403 jwk_dict->SetString("alg", "RS1"); | |
| 404 break; | |
| 405 case blink::WebCryptoAlgorithmIdSha256: | |
| 406 jwk_dict->SetString("alg", "RS256"); | |
| 407 break; | |
| 408 case blink::WebCryptoAlgorithmIdSha384: | |
| 409 jwk_dict->SetString("alg", "RS384"); | |
| 410 break; | |
| 411 case blink::WebCryptoAlgorithmIdSha512: | |
| 412 jwk_dict->SetString("alg", "RS512"); | |
| 413 break; | |
| 414 default: | |
| 415 NOTREACHED(); | |
| 416 return Status::ErrorUnexpected(); | |
| 417 } | |
| 418 break; | |
| 376 default: | 419 default: |
| 377 return Status::ErrorUnsupported(); | 420 return Status::ErrorUnsupported(); |
| 378 } | 421 } |
| 379 return Status::Success(); | 422 return Status::Success(); |
| 380 } | 423 } |
| 381 | 424 |
| 425 bool IsRsaPublicKey(const blink::WebCryptoKey& key) { | |
| 426 if (key.type() != blink::WebCryptoKeyTypePublic) | |
| 427 return false; | |
| 428 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); | |
| 429 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | |
| 430 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | |
| 431 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; | |
| 432 } | |
| 433 | |
| 434 // TODO(padolph): This function is duplicated in shared_crypto.cc | |
| 435 Status ToPlatformPublicKey(const blink::WebCryptoKey& key, | |
| 436 platform::PublicKey** out) { | |
| 437 *out = static_cast<platform::Key*>(key.handle())->AsPublicKey(); | |
| 438 if (!*out) | |
| 439 return Status::ErrorUnexpectedKeyType(); | |
| 440 return Status::Success(); | |
| 441 } | |
| 442 | |
| 382 } // namespace | 443 } // namespace |
| 383 | 444 |
| 384 Status ImportKeyJwk(const CryptoData& key_data, | 445 Status ImportKeyJwk(const CryptoData& key_data, |
| 385 const blink::WebCryptoAlgorithm& algorithm, | 446 const blink::WebCryptoAlgorithm& algorithm, |
| 386 bool extractable, | 447 bool extractable, |
| 387 blink::WebCryptoKeyUsageMask usage_mask, | 448 blink::WebCryptoKeyUsageMask usage_mask, |
| 388 blink::WebCryptoKey* key) { | 449 blink::WebCryptoKey* key) { |
| 389 // TODO(padolph): Generalize this comment to include export, and move to top | 450 // TODO(padolph): Generalize this comment to include export, and move to top |
| 390 // of file. | 451 // of file. |
| 391 | 452 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 // | 532 // |
| 472 // - alg (Algorithm) | 533 // - alg (Algorithm) |
| 473 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 | 534 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 |
| 474 // +--------------+-------------------------------------------------------+ | 535 // +--------------+-------------------------------------------------------+ |
| 475 // | Digital Signature or MAC Algorithm | | 536 // | Digital Signature or MAC Algorithm | |
| 476 // +--------------+-------------------------------------------------------+ | 537 // +--------------+-------------------------------------------------------+ |
| 477 // | "HS1" | HMAC using SHA-1 hash algorithm | | 538 // | "HS1" | HMAC using SHA-1 hash algorithm | |
| 478 // | "HS256" | HMAC using SHA-256 hash algorithm | | 539 // | "HS256" | HMAC using SHA-256 hash algorithm | |
| 479 // | "HS384" | HMAC using SHA-384 hash algorithm | | 540 // | "HS384" | HMAC using SHA-384 hash algorithm | |
| 480 // | "HS512" | HMAC using SHA-512 hash algorithm | | 541 // | "HS512" | HMAC using SHA-512 hash algorithm | |
| 542 // | "RS1" | RSASSA using SHA-1 hash algorithm | |
| 481 // | "RS256" | RSASSA using SHA-256 hash algorithm | | 543 // | "RS256" | RSASSA using SHA-256 hash algorithm | |
| 482 // | "RS384" | RSASSA using SHA-384 hash algorithm | | 544 // | "RS384" | RSASSA using SHA-384 hash algorithm | |
| 483 // | "RS512" | RSASSA using SHA-512 hash algorithm | | 545 // | "RS512" | RSASSA using SHA-512 hash algorithm | |
| 484 // +--------------+-------------------------------------------------------| | 546 // +--------------+-------------------------------------------------------| |
| 485 // | Key Management Algorithm | | 547 // | Key Management Algorithm | |
| 486 // +--------------+-------------------------------------------------------+ | 548 // +--------------+-------------------------------------------------------+ |
| 487 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | 549 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | |
| 488 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | 550 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | |
| 489 // | | (OAEP) [RFC3447], with the default parameters | | 551 // | | (OAEP) [RFC3447], with the default parameters | |
| 490 // | | specified by RFC3447 in Section A.2.1 | | 552 // | | 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), | 769 CryptoData(jwk_e_value), |
| 708 key); | 770 key); |
| 709 | 771 |
| 710 } | 772 } |
| 711 | 773 |
| 712 return Status::ErrorJwkUnrecognizedKty(); | 774 return Status::ErrorJwkUnrecognizedKty(); |
| 713 } | 775 } |
| 714 | 776 |
| 715 Status ExportKeyJwk(const blink::WebCryptoKey& key, | 777 Status ExportKeyJwk(const blink::WebCryptoKey& key, |
| 716 blink::WebArrayBuffer* buffer) { | 778 blink::WebArrayBuffer* buffer) { |
| 779 DCHECK(key.extractable()); | |
| 717 base::DictionaryValue jwk_dict; | 780 base::DictionaryValue jwk_dict; |
| 718 Status status = Status::Error(); | 781 Status status = Status::Error(); |
| 719 blink::WebArrayBuffer exported_key; | |
| 720 | 782 |
| 721 if (key.type() == blink::WebCryptoKeyTypeSecret) { | 783 unsigned int key_length_bytes = 0; |
|
eroman
2014/03/24 22:05:51
Delete this variable WriteAlg() no longer needs it
padolph
2014/03/25 01:10:28
Done.
| |
| 722 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); | 784 switch (key.type()) { |
| 723 if (status.IsError()) | 785 case blink::WebCryptoKeyTypeSecret: { |
| 724 return status; | 786 blink::WebArrayBuffer exported_key; |
| 725 WriteSecretKey(exported_key, &jwk_dict); | 787 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
| 726 } else { | 788 if (status.IsError()) |
| 727 // TODO(padolph): Handle asymmetric keys, at least the public key. | 789 return status; |
| 728 return Status::ErrorUnsupported(); | 790 key_length_bytes = exported_key.byteLength(); |
| 791 WriteSecretKey(exported_key, &jwk_dict); | |
| 792 break; | |
| 793 } | |
| 794 case blink::WebCryptoKeyTypePublic: { | |
| 795 // Currently only RSA public key export is supported. | |
| 796 if (!IsRsaPublicKey(key)) | |
| 797 return Status::ErrorUnsupported(); | |
| 798 platform::PublicKey* public_key; | |
| 799 status = ToPlatformPublicKey(key, &public_key); | |
| 800 if (status.IsError()) | |
| 801 return status; | |
| 802 std::vector<uint8> modulus, public_exponent; | |
|
eroman
2014/03/24 22:05:51
Please put these on two separate lines:
std::vect
padolph
2014/03/25 01:10:28
Done.
| |
| 803 status = | |
| 804 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); | |
| 805 if (status.IsError()) | |
| 806 return status; | |
| 807 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); | |
| 808 break; | |
| 809 } | |
| 810 case blink::WebCryptoKeyTypePrivate: // TODO(padolph) | |
| 811 default: | |
| 812 return Status::ErrorUnsupported(); | |
| 729 } | 813 } |
| 730 | 814 |
| 731 WriteKeyOps(key.usages(), &jwk_dict); | 815 WriteKeyOps(key.usages(), &jwk_dict); |
| 732 WriteExt(key.extractable(), &jwk_dict); | 816 WriteExt(key.extractable(), &jwk_dict); |
| 733 status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict); | 817 status = WriteAlg(key.algorithm(), key_length_bytes, &jwk_dict); |
| 734 if (status.IsError()) | 818 if (status.IsError()) |
| 735 return status; | 819 return status; |
| 736 | 820 |
| 737 std::string json; | 821 std::string json; |
| 738 base::JSONWriter::Write(&jwk_dict, &json); | 822 base::JSONWriter::Write(&jwk_dict, &json); |
| 739 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), | 823 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), |
| 740 json.size()); | 824 json.size()); |
| 741 return Status::Success(); | 825 return Status::Success(); |
| 742 } | 826 } |
| 743 | 827 |
| 744 } // namespace webcrypto | 828 } // namespace webcrypto |
| 745 | 829 |
| 746 } // namespace content | 830 } // namespace content |
| OLD | NEW |