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 "jwk.h" | 5 #include "jwk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <map> | 9 #include <map> |
10 | 10 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 // | "A192GCM" | AES GCM using 192 bit keys | | 123 // | "A192GCM" | AES GCM using 192 bit keys | |
124 // | "A256GCM" | AES GCM using 256 bit keys | | 124 // | "A256GCM" | AES GCM using 256 bit keys | |
125 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | | 125 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | |
126 // | | padding [NIST.800-38A] | | 126 // | | padding [NIST.800-38A] | |
127 // | "A192CBC" | AES CBC using 192 bit keys | | 127 // | "A192CBC" | AES CBC using 192 bit keys | |
128 // | "A256CBC" | AES CBC using 256 bit keys | | 128 // | "A256CBC" | AES CBC using 256 bit keys | |
129 // +--------------+-------------------------------------------------------+ | 129 // +--------------+-------------------------------------------------------+ |
130 // | 130 // |
131 // kty-specific parameters | 131 // kty-specific parameters |
132 // The value of kty determines the type and content of the keying material | 132 // The value of kty determines the type and content of the keying material |
133 // carried in the JWK to be imported. Currently only two possibilities are | 133 // carried in the JWK to be imported. |
134 // supported: a raw key or an RSA public key. RSA private keys are not | 134 // // - kty == "oct" (symmetric or other raw key) |
135 // supported because typical applications seldom need to import a private key, | |
136 // and the large number of JWK parameters required to describe one. | |
137 // - kty == "oct" (symmetric or other raw key) | |
138 // +-------+--------------------------------------------------------------+ | 135 // +-------+--------------------------------------------------------------+ |
139 // | "k" | Contains the value of the symmetric (or other single-valued) | | 136 // | "k" | Contains the value of the symmetric (or other single-valued) | |
140 // | | key. It is represented as the base64url encoding of the | | 137 // | | key. It is represented as the base64url encoding of the | |
141 // | | octet sequence containing the key value. | | 138 // | | octet sequence containing the key value. | |
142 // +-------+--------------------------------------------------------------+ | 139 // +-------+--------------------------------------------------------------+ |
143 // - kty == "RSA" (RSA public key) | 140 // - kty == "RSA" (RSA public key) |
144 // +-------+--------------------------------------------------------------+ | 141 // +-------+--------------------------------------------------------------+ |
145 // | "n" | Contains the modulus value for the RSA public key. It is | | 142 // | "n" | Contains the modulus value for the RSA public key. It is | |
146 // | | represented as the base64url encoding of the value's | | 143 // | | represented as the base64url encoding of the value's | |
147 // | | unsigned big endian representation as an octet sequence. | | 144 // | | unsigned big endian representation as an octet sequence. | |
148 // +-------+--------------------------------------------------------------+ | 145 // +-------+--------------------------------------------------------------+ |
149 // | "e" | Contains the exponent value for the RSA public key. It is | | 146 // | "e" | Contains the exponent value for the RSA public key. It is | |
150 // | | represented as the base64url encoding of the value's | | 147 // | | represented as the base64url encoding of the value's | |
151 // | | unsigned big endian representation as an octet sequence. | | 148 // | | unsigned big endian representation as an octet sequence. | |
152 // +-------+--------------------------------------------------------------+ | 149 // +-------+--------------------------------------------------------------+ |
| 150 // - If key == "RSA" and the "d" parameter is present then it is a private key. |
| 151 // All the parameters above for public keys apply, as well as the following. |
| 152 // (Note that except for "d", all of these are optional): |
| 153 // +-------+--------------------------------------------------------------+ |
| 154 // | "d" | Contains the private exponent value for the RSA private key. | |
| 155 // | | It is represented as the base64url encoding of the value's | |
| 156 // | | unsigned big endian representation as an octet sequence. | |
| 157 // +-------+--------------------------------------------------------------+ |
| 158 // | "p" | Contains the first prime factor value for the RSA private | |
| 159 // | | key. It is represented as the base64url encoding of the | |
| 160 // | | value's | |
| 161 // | | unsigned big endian representation as an octet sequence. | |
| 162 // +-------+--------------------------------------------------------------+ |
| 163 // | "q" | Contains the second prime factor value for the RSA private | |
| 164 // | | key. It is represented as the base64url encoding of the | |
| 165 // | | value's unsigned big endian representation as an octet | |
| 166 // | | sequence. | |
| 167 // +-------+--------------------------------------------------------------+ |
| 168 // | "dp" | Contains the first factor CRT exponent value for the RSA | |
| 169 // | | private key. It is represented as the base64url encoding of | |
| 170 // | | the value's unsigned big endian representation as an octet | |
| 171 // | | sequence. | |
| 172 // +-------+--------------------------------------------------------------+ |
| 173 // | "dq" | Contains the second factor CRT exponent value for the RSA | |
| 174 // | | private key. It is represented as the base64url encoding of | |
| 175 // | | the value's unsigned big endian representation as an octet | |
| 176 // | | sequence. | |
| 177 // +-------+--------------------------------------------------------------+ |
| 178 // | "dq" | Contains the first CRT coefficient value for the RSA private | |
| 179 // | | key. It is represented as the base64url encoding of the | |
| 180 // | | value's unsigned big endian representation as an octet | |
| 181 // | | sequence. | |
| 182 // +-------+--------------------------------------------------------------+ |
153 // | 183 // |
154 // Consistency and conflict resolution | 184 // Consistency and conflict resolution |
155 // The 'algorithm', 'extractable', and 'usage_mask' input parameters | 185 // The 'algorithm', 'extractable', and 'usage_mask' input parameters |
156 // may be different than the corresponding values inside the JWK. The Web | 186 // may be different than the corresponding values inside the JWK. The Web |
157 // Crypto spec says that if a JWK value is present but is inconsistent with | 187 // Crypto spec says that if a JWK value is present but is inconsistent with |
158 // the input value, it is an error and the operation must fail. If no | 188 // the input value, it is an error and the operation must fail. If no |
159 // inconsistency is found then the input parameters are used. | 189 // inconsistency is found then the input parameters are used. |
160 // | 190 // |
161 // algorithm | 191 // algorithm |
162 // If the JWK algorithm is provided, it must match the web crypto input | 192 // If the JWK algorithm is provided, it must match the web crypto input |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 Status status = GetJwkString(dict, path, &base64_string); | 453 Status status = GetJwkString(dict, path, &base64_string); |
424 if (status.IsError()) | 454 if (status.IsError()) |
425 return status; | 455 return status; |
426 | 456 |
427 if (!Base64DecodeUrlSafe(base64_string, result)) | 457 if (!Base64DecodeUrlSafe(base64_string, result)) |
428 return Status::ErrorJwkBase64Decode(path); | 458 return Status::ErrorJwkBase64Decode(path); |
429 | 459 |
430 return Status::Success(); | 460 return Status::Success(); |
431 } | 461 } |
432 | 462 |
| 463 // Extracts the optional string property with key |path| from |dict| and saves |
| 464 // the base64url-decoded bytes to |*result|. If the property exist and is not a |
| 465 // string, or could not be base64url-decoded, returns an error. In the case |
| 466 // where the property does not exist, |result| is guaranteed to be empty. |
| 467 Status GetOptionalJwkBytes(base::DictionaryValue* dict, |
| 468 const std::string& path, |
| 469 std::string* result, |
| 470 bool* property_exists) { |
| 471 std::string base64_string; |
| 472 Status status = |
| 473 GetOptionalJwkString(dict, path, &base64_string, property_exists); |
| 474 if (status.IsError()) |
| 475 return status; |
| 476 |
| 477 if (!*property_exists) { |
| 478 result->clear(); |
| 479 return Status::Success(); |
| 480 } |
| 481 |
| 482 if (!Base64DecodeUrlSafe(base64_string, result)) |
| 483 return Status::ErrorJwkBase64Decode(path); |
| 484 |
| 485 return Status::Success(); |
| 486 } |
| 487 |
433 // Extracts the optional boolean property with key |path| from |dict| and saves | 488 // Extracts the optional boolean property with key |path| from |dict| and saves |
434 // the result to |*result| if it was found. If the property exists and is not a | 489 // the result to |*result| if it was found. If the property exists and is not a |
435 // boolean, returns an error. Otherwise returns success, and sets | 490 // boolean, returns an error. Otherwise returns success, and sets |
436 // |*property_exists| if it was found. | 491 // |*property_exists| if it was found. |
437 Status GetOptionalJwkBool(base::DictionaryValue* dict, | 492 Status GetOptionalJwkBool(base::DictionaryValue* dict, |
438 const std::string& path, | 493 const std::string& path, |
439 bool* result, | 494 bool* result, |
440 bool* property_exists) { | 495 bool* property_exists) { |
441 *property_exists = false; | 496 *property_exists = false; |
442 base::Value* value = NULL; | 497 base::Value* value = NULL; |
(...skipping 30 matching lines...) Expand all Loading... |
473 const std::vector<uint8>& public_exponent, | 528 const std::vector<uint8>& public_exponent, |
474 base::DictionaryValue* jwk_dict) { | 529 base::DictionaryValue* jwk_dict) { |
475 DCHECK(jwk_dict); | 530 DCHECK(jwk_dict); |
476 DCHECK(modulus.size()); | 531 DCHECK(modulus.size()); |
477 DCHECK(public_exponent.size()); | 532 DCHECK(public_exponent.size()); |
478 jwk_dict->SetString("kty", "RSA"); | 533 jwk_dict->SetString("kty", "RSA"); |
479 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus)); | 534 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus)); |
480 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent)); | 535 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent)); |
481 } | 536 } |
482 | 537 |
| 538 // Writes an RSA private key to a JWK dictionary |
| 539 Status ExportRsaPrivateKeyJwk(const blink::WebCryptoKey& key, |
| 540 base::DictionaryValue* jwk_dict) { |
| 541 platform::PrivateKey* private_key; |
| 542 Status status = ToPlatformPrivateKey(key, &private_key); |
| 543 if (status.IsError()) |
| 544 return status; |
| 545 |
| 546 // TODO(eroman): Copying the key properties to temporary vectors is |
| 547 // inefficient. Once there aren't two implementations of platform_crypto this |
| 548 // and other code will be easier to streamline. |
| 549 std::vector<uint8> modulus; |
| 550 std::vector<uint8> public_exponent; |
| 551 std::vector<uint8> private_exponent; |
| 552 std::vector<uint8> prime1; |
| 553 std::vector<uint8> prime2; |
| 554 std::vector<uint8> exponent1; |
| 555 std::vector<uint8> exponent2; |
| 556 std::vector<uint8> coefficient; |
| 557 |
| 558 status = platform::ExportRsaPrivateKey(private_key, |
| 559 &modulus, |
| 560 &public_exponent, |
| 561 &private_exponent, |
| 562 &prime1, |
| 563 &prime2, |
| 564 &exponent1, |
| 565 &exponent2, |
| 566 &coefficient); |
| 567 if (status.IsError()) |
| 568 return status; |
| 569 |
| 570 jwk_dict->SetString("kty", "RSA"); |
| 571 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus)); |
| 572 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent)); |
| 573 jwk_dict->SetString("d", Base64EncodeUrlSafe(private_exponent)); |
| 574 // Although these are "optional" in the JWA, WebCrypto spec requires them to |
| 575 // be emitted. |
| 576 jwk_dict->SetString("p", Base64EncodeUrlSafe(prime1)); |
| 577 jwk_dict->SetString("q", Base64EncodeUrlSafe(prime2)); |
| 578 jwk_dict->SetString("dp", Base64EncodeUrlSafe(exponent1)); |
| 579 jwk_dict->SetString("dq", Base64EncodeUrlSafe(exponent2)); |
| 580 jwk_dict->SetString("qi", Base64EncodeUrlSafe(coefficient)); |
| 581 |
| 582 return Status::Success(); |
| 583 } |
| 584 |
483 // Writes a Web Crypto usage mask to a JWK dictionary. | 585 // Writes a Web Crypto usage mask to a JWK dictionary. |
484 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, | 586 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, |
485 base::DictionaryValue* jwk_dict) { | 587 base::DictionaryValue* jwk_dict) { |
486 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); | 588 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); |
487 } | 589 } |
488 | 590 |
489 // Writes a Web Crypto extractable value to a JWK dictionary. | 591 // Writes a Web Crypto extractable value to a JWK dictionary. |
490 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { | 592 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { |
491 jwk_dict->SetBoolean("ext", extractable); | 593 jwk_dict->SetBoolean("ext", extractable); |
492 } | 594 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 NOTREACHED(); | 687 NOTREACHED(); |
586 return Status::ErrorUnexpected(); | 688 return Status::ErrorUnexpected(); |
587 } | 689 } |
588 break; | 690 break; |
589 default: | 691 default: |
590 return Status::ErrorUnsupported(); | 692 return Status::ErrorUnsupported(); |
591 } | 693 } |
592 return Status::Success(); | 694 return Status::Success(); |
593 } | 695 } |
594 | 696 |
595 bool IsRsaPublicKey(const blink::WebCryptoKey& key) { | 697 bool IsRsaKey(const blink::WebCryptoKey& key) { |
596 if (key.type() != blink::WebCryptoKeyTypePublic) | |
597 return false; | |
598 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); | 698 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id(); |
599 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | 699 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
600 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | 700 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
601 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; | 701 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep; |
602 } | 702 } |
603 | 703 |
604 // TODO(padolph): This function is duplicated in shared_crypto.cc | 704 Status ImportRsaKey(base::DictionaryValue* dict, |
605 Status ToPlatformPublicKey(const blink::WebCryptoKey& key, | 705 const blink::WebCryptoAlgorithm& algorithm, |
606 platform::PublicKey** out) { | 706 bool extractable, |
607 *out = static_cast<platform::Key*>(key.handle())->AsPublicKey(); | 707 blink::WebCryptoKeyUsageMask usage_mask, |
608 if (!*out) | 708 blink::WebCryptoKey* key) { |
609 return Status::ErrorUnexpectedKeyType(); | 709 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry |
610 return Status::Success(); | 710 // in the JWK, while an RSA private key must have those, plus at least a "d" |
| 711 // (private exponent) entry. |
| 712 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, |
| 713 // section 6.3. |
| 714 std::string jwk_n_value; |
| 715 Status status = GetJwkBytes(dict, "n", &jwk_n_value); |
| 716 if (status.IsError()) |
| 717 return status; |
| 718 std::string jwk_e_value; |
| 719 status = GetJwkBytes(dict, "e", &jwk_e_value); |
| 720 if (status.IsError()) |
| 721 return status; |
| 722 |
| 723 if (!dict->HasKey("d")) { |
| 724 return platform::ImportRsaPublicKey(algorithm, |
| 725 extractable, |
| 726 usage_mask, |
| 727 CryptoData(jwk_n_value), |
| 728 CryptoData(jwk_e_value), |
| 729 key); |
| 730 } |
| 731 |
| 732 std::string jwk_d_value; |
| 733 status = GetJwkBytes(dict, "d", &jwk_d_value); |
| 734 if (status.IsError()) |
| 735 return status; |
| 736 |
| 737 // The "p", "q", "dp", "dq", and "qi" properties are optional. Treat these |
| 738 // properties the same if they are unspecified, as if they were specified-but |
| 739 // empty, since ImportRsaPrivateKey() doesn't do validation checks anyway. |
| 740 |
| 741 std::string jwk_p_value; |
| 742 bool has_p; |
| 743 status = GetOptionalJwkBytes(dict, "p", &jwk_p_value, &has_p); |
| 744 if (status.IsError()) |
| 745 return status; |
| 746 |
| 747 std::string jwk_q_value; |
| 748 bool has_q; |
| 749 status = GetOptionalJwkBytes(dict, "q", &jwk_q_value, &has_q); |
| 750 if (status.IsError()) |
| 751 return status; |
| 752 |
| 753 std::string jwk_dp_value; |
| 754 bool has_dp; |
| 755 status = GetOptionalJwkBytes(dict, "dp", &jwk_dp_value, &has_dp); |
| 756 if (status.IsError()) |
| 757 return status; |
| 758 |
| 759 std::string jwk_dq_value; |
| 760 bool has_dq; |
| 761 status = GetOptionalJwkBytes(dict, "dq", &jwk_dq_value, &has_dq); |
| 762 if (status.IsError()) |
| 763 return status; |
| 764 |
| 765 std::string jwk_qi_value; |
| 766 bool has_qi; |
| 767 status = GetOptionalJwkBytes(dict, "qi", &jwk_qi_value, &has_qi); |
| 768 if (status.IsError()) |
| 769 return status; |
| 770 |
| 771 int num_optional_properties = has_p + has_q + has_dp + has_dq + has_qi; |
| 772 if (num_optional_properties != 0 && num_optional_properties != 5) |
| 773 return Status::ErrorJwkIncompleteOptionalRsaPrivateKey(); |
| 774 |
| 775 return platform::ImportRsaPrivateKey( |
| 776 algorithm, |
| 777 extractable, |
| 778 usage_mask, |
| 779 CryptoData(jwk_n_value), // modulus |
| 780 CryptoData(jwk_e_value), // public_exponent |
| 781 CryptoData(jwk_d_value), // private_exponent |
| 782 CryptoData(jwk_p_value), // prime1 |
| 783 CryptoData(jwk_q_value), // prime2 |
| 784 CryptoData(jwk_dp_value), // exponent1 |
| 785 CryptoData(jwk_dq_value), // exponent2 |
| 786 CryptoData(jwk_qi_value), // coefficient |
| 787 key); |
611 } | 788 } |
612 | 789 |
613 } // namespace | 790 } // namespace |
614 | 791 |
| 792 // TODO(eroman): Split this up into smaller functions. |
615 Status ImportKeyJwk(const CryptoData& key_data, | 793 Status ImportKeyJwk(const CryptoData& key_data, |
616 const blink::WebCryptoAlgorithm& algorithm, | 794 const blink::WebCryptoAlgorithm& algorithm, |
617 bool extractable, | 795 bool extractable, |
618 blink::WebCryptoKeyUsageMask usage_mask, | 796 blink::WebCryptoKeyUsageMask usage_mask, |
619 blink::WebCryptoKey* key) { | 797 blink::WebCryptoKey* key) { |
620 if (!key_data.byte_length()) | 798 if (!key_data.byte_length()) |
621 return Status::ErrorImportEmptyKeyData(); | 799 return Status::ErrorImportEmptyKeyData(); |
622 DCHECK(key); | 800 DCHECK(key); |
623 | 801 |
624 // Parse the incoming JWK JSON. | 802 // Parse the incoming JWK JSON. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 return Status::ErrorJwkIncorrectKeyLength(); | 918 return Status::ErrorJwkIncorrectKeyLength(); |
741 } | 919 } |
742 | 920 |
743 return ImportKey(blink::WebCryptoKeyFormatRaw, | 921 return ImportKey(blink::WebCryptoKeyFormatRaw, |
744 CryptoData(jwk_k_value), | 922 CryptoData(jwk_k_value), |
745 algorithm, | 923 algorithm, |
746 extractable, | 924 extractable, |
747 usage_mask, | 925 usage_mask, |
748 key); | 926 key); |
749 } | 927 } |
750 if (jwk_kty_value == "RSA") { | |
751 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry | |
752 // in the JWK, while an RSA private key must have those, plus at least a "d" | |
753 // (private exponent) entry. | |
754 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, | |
755 // section 6.3. | |
756 | 928 |
757 // RSA private key import is not currently supported, so fail here if a "d" | 929 if (jwk_kty_value == "RSA") |
758 // entry is found. | 930 return ImportRsaKey(dict_value, algorithm, extractable, usage_mask, key); |
759 // TODO(padolph): Support RSA private key import. | |
760 if (dict_value->HasKey("d")) | |
761 return Status::ErrorJwkRsaPrivateKeyUnsupported(); | |
762 | |
763 std::string jwk_n_value; | |
764 status = GetJwkBytes(dict_value, "n", &jwk_n_value); | |
765 if (status.IsError()) | |
766 return status; | |
767 std::string jwk_e_value; | |
768 status = GetJwkBytes(dict_value, "e", &jwk_e_value); | |
769 if (status.IsError()) | |
770 return status; | |
771 | |
772 return platform::ImportRsaPublicKey(algorithm, | |
773 extractable, | |
774 usage_mask, | |
775 CryptoData(jwk_n_value), | |
776 CryptoData(jwk_e_value), | |
777 key); | |
778 | |
779 } | |
780 | 931 |
781 return Status::ErrorJwkUnrecognizedKty(); | 932 return Status::ErrorJwkUnrecognizedKty(); |
782 } | 933 } |
783 | 934 |
784 Status ExportKeyJwk(const blink::WebCryptoKey& key, | 935 Status ExportKeyJwk(const blink::WebCryptoKey& key, |
785 std::vector<uint8>* buffer) { | 936 std::vector<uint8>* buffer) { |
786 DCHECK(key.extractable()); | 937 DCHECK(key.extractable()); |
787 base::DictionaryValue jwk_dict; | 938 base::DictionaryValue jwk_dict; |
788 Status status = Status::OperationError(); | 939 Status status = Status::OperationError(); |
789 | 940 |
790 switch (key.type()) { | 941 switch (key.type()) { |
791 case blink::WebCryptoKeyTypeSecret: { | 942 case blink::WebCryptoKeyTypeSecret: { |
792 std::vector<uint8> exported_key; | 943 std::vector<uint8> exported_key; |
793 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); | 944 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); |
794 if (status.IsError()) | 945 if (status.IsError()) |
795 return status; | 946 return status; |
796 WriteSecretKey(exported_key, &jwk_dict); | 947 WriteSecretKey(exported_key, &jwk_dict); |
797 break; | 948 break; |
798 } | 949 } |
799 case blink::WebCryptoKeyTypePublic: { | 950 case blink::WebCryptoKeyTypePublic: { |
800 // Currently only RSA public key export is supported. | 951 // TODO(eroman): Update when there are asymmetric keys other than RSA. |
801 if (!IsRsaPublicKey(key)) | 952 if (!IsRsaKey(key)) |
802 return Status::ErrorUnsupported(); | 953 return Status::ErrorUnsupported(); |
803 platform::PublicKey* public_key; | 954 platform::PublicKey* public_key; |
804 status = ToPlatformPublicKey(key, &public_key); | 955 status = ToPlatformPublicKey(key, &public_key); |
805 if (status.IsError()) | 956 if (status.IsError()) |
806 return status; | 957 return status; |
807 std::vector<uint8> modulus; | 958 std::vector<uint8> modulus; |
808 std::vector<uint8> public_exponent; | 959 std::vector<uint8> public_exponent; |
809 status = | 960 status = |
810 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); | 961 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent); |
811 if (status.IsError()) | 962 if (status.IsError()) |
812 return status; | 963 return status; |
813 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); | 964 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict); |
814 break; | 965 break; |
815 } | 966 } |
816 case blink::WebCryptoKeyTypePrivate: // TODO(padolph) | 967 case blink::WebCryptoKeyTypePrivate: { |
| 968 // TODO(eroman): Update when there are asymmetric keys other than RSA. |
| 969 if (!IsRsaKey(key)) |
| 970 return Status::ErrorUnsupported(); |
| 971 |
| 972 status = ExportRsaPrivateKeyJwk(key, &jwk_dict); |
| 973 if (status.IsError()) |
| 974 return status; |
| 975 break; |
| 976 } |
| 977 |
817 default: | 978 default: |
818 return Status::ErrorUnsupported(); | 979 return Status::ErrorUnsupported(); |
819 } | 980 } |
820 | 981 |
821 WriteKeyOps(key.usages(), &jwk_dict); | 982 WriteKeyOps(key.usages(), &jwk_dict); |
822 WriteExt(key.extractable(), &jwk_dict); | 983 WriteExt(key.extractable(), &jwk_dict); |
823 status = WriteAlg(key.algorithm(), &jwk_dict); | 984 status = WriteAlg(key.algorithm(), &jwk_dict); |
824 if (status.IsError()) | 985 if (status.IsError()) |
825 return status; | 986 return status; |
826 | 987 |
827 std::string json; | 988 std::string json; |
828 base::JSONWriter::Write(&jwk_dict, &json); | 989 base::JSONWriter::Write(&jwk_dict, &json); |
829 buffer->assign(json.data(), json.data() + json.size()); | 990 buffer->assign(json.data(), json.data() + json.size()); |
830 return Status::Success(); | 991 return Status::Success(); |
831 } | 992 } |
832 | 993 |
833 } // namespace webcrypto | 994 } // namespace webcrypto |
834 | 995 |
835 } // namespace content | 996 } // namespace content |
OLD | NEW |