| 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 "content/child/webcrypto/nss/rsa_key_nss.h" | 5 #include "content/child/webcrypto/nss/rsa_key_nss.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
| 9 #include "content/child/webcrypto/jwk.h" | 9 #include "content/child/webcrypto/jwk.h" |
| 10 #include "content/child/webcrypto/nss/key_nss.h" | 10 #include "content/child/webcrypto/nss/key_nss.h" |
| 11 #include "content/child/webcrypto/nss/util_nss.h" | 11 #include "content/child/webcrypto/nss/util_nss.h" |
| 12 #include "content/child/webcrypto/status.h" | 12 #include "content/child/webcrypto/status.h" |
| 13 #include "content/child/webcrypto/webcrypto_util.h" | 13 #include "content/child/webcrypto/webcrypto_util.h" |
| 14 #include "crypto/scoped_nss_types.h" | 14 #include "crypto/scoped_nss_types.h" |
| 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| 16 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 16 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
| 17 | 17 |
| 18 namespace content { | 18 namespace content { |
| 19 | 19 |
| 20 namespace webcrypto { | 20 namespace webcrypto { |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, | 24 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, |
| 25 // to unsigned long. | 25 // to unsigned long. |
| 26 bool BigIntegerToLong(const uint8* data, | 26 bool BigIntegerToLong(const uint8_t* data, |
| 27 unsigned int data_size, | 27 unsigned int data_size, |
| 28 unsigned long* result) { | 28 unsigned long* result) { |
| 29 // TODO(eroman): Fix handling of empty biginteger. http://crubg.com/373552 | 29 // TODO(eroman): Fix handling of empty biginteger. http://crubg.com/373552 |
| 30 if (data_size == 0) | 30 if (data_size == 0) |
| 31 return false; | 31 return false; |
| 32 | 32 |
| 33 *result = 0; | 33 *result = 0; |
| 34 for (size_t i = 0; i < data_size; ++i) { | 34 for (size_t i = 0; i < data_size; ++i) { |
| 35 size_t reverse_i = data_size - i - 1; | 35 size_t reverse_i = data_size - i - 1; |
| 36 | 36 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 data.byte_length()}; | 303 data.byte_length()}; |
| 304 templ->push_back(attribute); | 304 templ->push_back(attribute); |
| 305 } | 305 } |
| 306 | 306 |
| 307 void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type, | 307 void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type, |
| 308 const std::string& data, | 308 const std::string& data, |
| 309 std::vector<CK_ATTRIBUTE>* templ) { | 309 std::vector<CK_ATTRIBUTE>* templ) { |
| 310 AddOptionalAttribute(type, CryptoData(data), templ); | 310 AddOptionalAttribute(type, CryptoData(data), templ); |
| 311 } | 311 } |
| 312 | 312 |
| 313 Status ExportKeyPkcs8Nss(SECKEYPrivateKey* key, std::vector<uint8>* buffer) { | 313 Status ExportKeyPkcs8Nss(SECKEYPrivateKey* key, std::vector<uint8_t>* buffer) { |
| 314 if (key->keyType != rsaKey) | 314 if (key->keyType != rsaKey) |
| 315 return Status::ErrorUnsupported(); | 315 return Status::ErrorUnsupported(); |
| 316 | 316 |
| 317 // TODO(rsleevi): Implement OAEP support according to the spec. | 317 // TODO(rsleevi): Implement OAEP support according to the spec. |
| 318 | 318 |
| 319 #if defined(USE_NSS) | 319 #if defined(USE_NSS) |
| 320 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. | 320 // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code. |
| 321 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; | 321 const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
| 322 const int kPrivateKeyInfoVersion = 0; | 322 const int kPrivateKeyInfoVersion = 0; |
| 323 | 323 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 crypto::ScopedSECKEYPrivateKey private_key( | 445 crypto::ScopedSECKEYPrivateKey private_key( |
| 446 SECKEY_CopyPrivateKey(private_key_tmp.get())); | 446 SECKEY_CopyPrivateKey(private_key_tmp.get())); |
| 447 | 447 |
| 448 if (!private_key) | 448 if (!private_key) |
| 449 return Status::OperationError(); | 449 return Status::OperationError(); |
| 450 | 450 |
| 451 blink::WebCryptoKeyAlgorithm key_algorithm; | 451 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 452 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 452 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) |
| 453 return Status::ErrorUnexpected(); | 453 return Status::ErrorUnexpected(); |
| 454 | 454 |
| 455 std::vector<uint8> pkcs8_data; | 455 std::vector<uint8_t> pkcs8_data; |
| 456 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); | 456 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); |
| 457 if (status.IsError()) | 457 if (status.IsError()) |
| 458 return status; | 458 return status; |
| 459 | 459 |
| 460 scoped_ptr<PrivateKeyNss> key_handle( | 460 scoped_ptr<PrivateKeyNss> key_handle( |
| 461 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); | 461 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); |
| 462 | 462 |
| 463 *key = blink::WebCryptoKey::create(key_handle.release(), | 463 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 464 blink::WebCryptoKeyTypePrivate, | 464 blink::WebCryptoKeyTypePrivate, |
| 465 extractable, | 465 extractable, |
| 466 key_algorithm, | 466 key_algorithm, |
| 467 usage_mask); | 467 usage_mask); |
| 468 return Status::Success(); | 468 return Status::Success(); |
| 469 } | 469 } |
| 470 | 470 |
| 471 Status ExportKeySpkiNss(SECKEYPublicKey* key, std::vector<uint8>* buffer) { | 471 Status ExportKeySpkiNss(SECKEYPublicKey* key, std::vector<uint8_t>* buffer) { |
| 472 const crypto::ScopedSECItem spki_der( | 472 const crypto::ScopedSECItem spki_der( |
| 473 SECKEY_EncodeDERSubjectPublicKeyInfo(key)); | 473 SECKEY_EncodeDERSubjectPublicKeyInfo(key)); |
| 474 if (!spki_der) | 474 if (!spki_der) |
| 475 return Status::OperationError(); | 475 return Status::OperationError(); |
| 476 | 476 |
| 477 buffer->assign(spki_der->data, spki_der->data + spki_der->len); | 477 buffer->assign(spki_der->data, spki_der->data + spki_der->len); |
| 478 return Status::Success(); | 478 return Status::Success(); |
| 479 } | 479 } |
| 480 | 480 |
| 481 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, | 481 Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. | 531 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. |
| 532 crypto::ScopedSECKEYPublicKey pubkey( | 532 crypto::ScopedSECKEYPublicKey pubkey( |
| 533 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); | 533 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); |
| 534 if (!pubkey) | 534 if (!pubkey) |
| 535 return Status::OperationError(); | 535 return Status::OperationError(); |
| 536 | 536 |
| 537 blink::WebCryptoKeyAlgorithm key_algorithm; | 537 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 538 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) | 538 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) |
| 539 return Status::ErrorUnexpected(); | 539 return Status::ErrorUnexpected(); |
| 540 | 540 |
| 541 std::vector<uint8> spki_data; | 541 std::vector<uint8_t> spki_data; |
| 542 Status status = ExportKeySpkiNss(pubkey.get(), &spki_data); | 542 Status status = ExportKeySpkiNss(pubkey.get(), &spki_data); |
| 543 if (status.IsError()) | 543 if (status.IsError()) |
| 544 return status; | 544 return status; |
| 545 | 545 |
| 546 scoped_ptr<PublicKeyNss> key_handle( | 546 scoped_ptr<PublicKeyNss> key_handle( |
| 547 new PublicKeyNss(pubkey.Pass(), CryptoData(spki_data))); | 547 new PublicKeyNss(pubkey.Pass(), CryptoData(spki_data))); |
| 548 | 548 |
| 549 *key = blink::WebCryptoKey::create(key_handle.release(), | 549 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 550 blink::WebCryptoKeyTypePublic, | 550 blink::WebCryptoKeyTypePublic, |
| 551 extractable, | 551 extractable, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 generate_flags_, | 623 generate_flags_, |
| 624 operation_flags_mask, | 624 operation_flags_mask, |
| 625 NULL)); | 625 NULL)); |
| 626 if (!scoped_sec_private_key) | 626 if (!scoped_sec_private_key) |
| 627 return Status::OperationError(); | 627 return Status::OperationError(); |
| 628 | 628 |
| 629 blink::WebCryptoKeyAlgorithm key_algorithm; | 629 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 630 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) | 630 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) |
| 631 return Status::ErrorUnexpected(); | 631 return Status::ErrorUnexpected(); |
| 632 | 632 |
| 633 std::vector<uint8> spki_data; | 633 std::vector<uint8_t> spki_data; |
| 634 Status status = ExportKeySpkiNss(sec_public_key, &spki_data); | 634 Status status = ExportKeySpkiNss(sec_public_key, &spki_data); |
| 635 if (status.IsError()) | 635 if (status.IsError()) |
| 636 return status; | 636 return status; |
| 637 | 637 |
| 638 scoped_ptr<PublicKeyNss> public_key_handle(new PublicKeyNss( | 638 scoped_ptr<PublicKeyNss> public_key_handle(new PublicKeyNss( |
| 639 crypto::ScopedSECKEYPublicKey(sec_public_key), CryptoData(spki_data))); | 639 crypto::ScopedSECKEYPublicKey(sec_public_key), CryptoData(spki_data))); |
| 640 | 640 |
| 641 std::vector<uint8> pkcs8_data; | 641 std::vector<uint8_t> pkcs8_data; |
| 642 status = ExportKeyPkcs8Nss(scoped_sec_private_key.get(), &pkcs8_data); | 642 status = ExportKeyPkcs8Nss(scoped_sec_private_key.get(), &pkcs8_data); |
| 643 if (status.IsError()) | 643 if (status.IsError()) |
| 644 return status; | 644 return status; |
| 645 | 645 |
| 646 scoped_ptr<PrivateKeyNss> private_key_handle( | 646 scoped_ptr<PrivateKeyNss> private_key_handle( |
| 647 new PrivateKeyNss(scoped_sec_private_key.Pass(), CryptoData(pkcs8_data))); | 647 new PrivateKeyNss(scoped_sec_private_key.Pass(), CryptoData(pkcs8_data))); |
| 648 | 648 |
| 649 *public_key = blink::WebCryptoKey::create(public_key_handle.release(), | 649 *public_key = blink::WebCryptoKey::create(public_key_handle.release(), |
| 650 blink::WebCryptoKeyTypePublic, | 650 blink::WebCryptoKeyTypePublic, |
| 651 true, | 651 true, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 712 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
| 713 if (sec_key_type != rsaKey) | 713 if (sec_key_type != rsaKey) |
| 714 return Status::DataError(); | 714 return Status::DataError(); |
| 715 | 715 |
| 716 blink::WebCryptoKeyAlgorithm key_algorithm; | 716 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 717 if (!CreateRsaHashedPrivateKeyAlgorithm( | 717 if (!CreateRsaHashedPrivateKeyAlgorithm( |
| 718 algorithm, private_key.get(), &key_algorithm)) | 718 algorithm, private_key.get(), &key_algorithm)) |
| 719 return Status::ErrorUnexpected(); | 719 return Status::ErrorUnexpected(); |
| 720 | 720 |
| 721 // TODO(eroman): This is probably going to be the same as the input. | 721 // TODO(eroman): This is probably going to be the same as the input. |
| 722 std::vector<uint8> pkcs8_data; | 722 std::vector<uint8_t> pkcs8_data; |
| 723 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); | 723 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); |
| 724 if (status.IsError()) | 724 if (status.IsError()) |
| 725 return status; | 725 return status; |
| 726 | 726 |
| 727 scoped_ptr<PrivateKeyNss> key_handle( | 727 scoped_ptr<PrivateKeyNss> key_handle( |
| 728 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); | 728 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); |
| 729 | 729 |
| 730 *key = blink::WebCryptoKey::create(key_handle.release(), | 730 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 731 blink::WebCryptoKeyTypePrivate, | 731 blink::WebCryptoKeyTypePrivate, |
| 732 extractable, | 732 extractable, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 765 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 766 if (sec_key_type != rsaKey) | 766 if (sec_key_type != rsaKey) |
| 767 return Status::DataError(); | 767 return Status::DataError(); |
| 768 | 768 |
| 769 blink::WebCryptoKeyAlgorithm key_algorithm; | 769 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 770 if (!CreateRsaHashedPublicKeyAlgorithm( | 770 if (!CreateRsaHashedPublicKeyAlgorithm( |
| 771 algorithm, sec_public_key.get(), &key_algorithm)) | 771 algorithm, sec_public_key.get(), &key_algorithm)) |
| 772 return Status::ErrorUnexpected(); | 772 return Status::ErrorUnexpected(); |
| 773 | 773 |
| 774 // TODO(eroman): This is probably going to be the same as the input. | 774 // TODO(eroman): This is probably going to be the same as the input. |
| 775 std::vector<uint8> spki_data; | 775 std::vector<uint8_t> spki_data; |
| 776 status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); | 776 status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); |
| 777 if (status.IsError()) | 777 if (status.IsError()) |
| 778 return status; | 778 return status; |
| 779 | 779 |
| 780 scoped_ptr<PublicKeyNss> key_handle( | 780 scoped_ptr<PublicKeyNss> key_handle( |
| 781 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); | 781 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); |
| 782 | 782 |
| 783 *key = blink::WebCryptoKey::create(key_handle.release(), | 783 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 784 blink::WebCryptoKeyTypePublic, | 784 blink::WebCryptoKeyTypePublic, |
| 785 extractable, | 785 extractable, |
| 786 key_algorithm, | 786 key_algorithm, |
| 787 usage_mask); | 787 usage_mask); |
| 788 | 788 |
| 789 return Status::Success(); | 789 return Status::Success(); |
| 790 } | 790 } |
| 791 | 791 |
| 792 Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, | 792 Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, |
| 793 std::vector<uint8>* buffer) const { | 793 std::vector<uint8_t>* buffer) const { |
| 794 if (key.type() != blink::WebCryptoKeyTypePrivate) | 794 if (key.type() != blink::WebCryptoKeyTypePrivate) |
| 795 return Status::ErrorUnexpectedKeyType(); | 795 return Status::ErrorUnexpectedKeyType(); |
| 796 *buffer = PrivateKeyNss::Cast(key)->pkcs8_data(); | 796 *buffer = PrivateKeyNss::Cast(key)->pkcs8_data(); |
| 797 return Status::Success(); | 797 return Status::Success(); |
| 798 } | 798 } |
| 799 | 799 |
| 800 Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, | 800 Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, |
| 801 std::vector<uint8>* buffer) const { | 801 std::vector<uint8_t>* buffer) const { |
| 802 if (key.type() != blink::WebCryptoKeyTypePublic) | 802 if (key.type() != blink::WebCryptoKeyTypePublic) |
| 803 return Status::ErrorUnexpectedKeyType(); | 803 return Status::ErrorUnexpectedKeyType(); |
| 804 *buffer = PublicKeyNss::Cast(key)->spki_data(); | 804 *buffer = PublicKeyNss::Cast(key)->spki_data(); |
| 805 return Status::Success(); | 805 return Status::Success(); |
| 806 } | 806 } |
| 807 | 807 |
| 808 Status RsaHashedAlgorithm::ImportKeyJwk( | 808 Status RsaHashedAlgorithm::ImportKeyJwk( |
| 809 const CryptoData& key_data, | 809 const CryptoData& key_data, |
| 810 const blink::WebCryptoAlgorithm& algorithm, | 810 const blink::WebCryptoAlgorithm& algorithm, |
| 811 bool extractable, | 811 bool extractable, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 834 ? ImportRsaPrivateKey(algorithm, extractable, usage_mask, jwk, key) | 834 ? ImportRsaPrivateKey(algorithm, extractable, usage_mask, jwk, key) |
| 835 : ImportRsaPublicKey(algorithm, | 835 : ImportRsaPublicKey(algorithm, |
| 836 extractable, | 836 extractable, |
| 837 usage_mask, | 837 usage_mask, |
| 838 CryptoData(jwk.n), | 838 CryptoData(jwk.n), |
| 839 CryptoData(jwk.e), | 839 CryptoData(jwk.e), |
| 840 key); | 840 key); |
| 841 } | 841 } |
| 842 | 842 |
| 843 Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, | 843 Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key, |
| 844 std::vector<uint8>* buffer) const { | 844 std::vector<uint8_t>* buffer) const { |
| 845 const char* jwk_algorithm = | 845 const char* jwk_algorithm = |
| 846 GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id()); | 846 GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id()); |
| 847 | 847 |
| 848 if (!jwk_algorithm) | 848 if (!jwk_algorithm) |
| 849 return Status::ErrorUnexpected(); | 849 return Status::ErrorUnexpected(); |
| 850 | 850 |
| 851 switch (key.type()) { | 851 switch (key.type()) { |
| 852 case blink::WebCryptoKeyTypePublic: { | 852 case blink::WebCryptoKeyTypePublic: { |
| 853 SECKEYPublicKey* nss_key = PublicKeyNss::Cast(key)->key(); | 853 SECKEYPublicKey* nss_key = PublicKeyNss::Cast(key)->key(); |
| 854 if (nss_key->keyType != rsaKey) | 854 if (nss_key->keyType != rsaKey) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 return Status::Success(); | 888 return Status::Success(); |
| 889 } | 889 } |
| 890 default: | 890 default: |
| 891 return Status::ErrorUnexpected(); | 891 return Status::ErrorUnexpected(); |
| 892 } | 892 } |
| 893 } | 893 } |
| 894 | 894 |
| 895 } // namespace webcrypto | 895 } // namespace webcrypto |
| 896 | 896 |
| 897 } // namespace content | 897 } // namespace content |
| OLD | NEW |