| 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" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 } | 48 } |
| 49 | 49 |
| 50 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | 50 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, |
| 51 SECKEYPrivateKey* key, | 51 SECKEYPrivateKey* key, |
| 52 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 52 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 53 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); | 53 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); |
| 54 return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm); | 54 return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm); |
| 55 } | 55 } |
| 56 | 56 |
| 57 #if defined(USE_NSS) && !defined(OS_CHROMEOS) | 57 #if defined(USE_NSS) && !defined(OS_CHROMEOS) |
| 58 Status ErrorRsaKeyImportNotSupported() { | 58 Status ErrorRsaPrivateKeyImportNotSupported() { |
| 59 return Status::ErrorUnsupported( | 59 return Status::ErrorUnsupported( |
| 60 "NSS version must be at least 3.16.2 for RSA key import. See " | 60 "NSS version must be at least 3.16.2 for RSA private key import. See " |
| 61 "http://crbug.com/380424"); | 61 "http://crbug.com/380424"); |
| 62 } | 62 } |
| 63 | 63 |
| 64 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is | 64 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is |
| 65 // a security problem for RSA private key import from JWK which uses a | 65 // a security problem for RSA private key import from JWK which uses a |
| 66 // CKA_ID based on the public modulus to retrieve the private key. | 66 // CKA_ID based on the public modulus to retrieve the private key. |
| 67 Status NssSupportsRsaKeyImport() { | 67 Status NssSupportsRsaPrivateKeyImport() { |
| 68 if (!NSS_VersionCheck("3.16.2")) | 68 if (!NSS_VersionCheck("3.16.2")) |
| 69 return ErrorRsaKeyImportNotSupported(); | 69 return ErrorRsaPrivateKeyImportNotSupported(); |
| 70 | 70 |
| 71 // Also ensure that the version of Softoken is 3.16.2 or later. | 71 // Also ensure that the version of Softoken is 3.16.2 or later. |
| 72 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); | 72 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); |
| 73 CK_SLOT_INFO info = {}; | 73 CK_SLOT_INFO info = {}; |
| 74 if (PK11_GetSlotInfo(slot.get(), &info) != SECSuccess) | 74 if (PK11_GetSlotInfo(slot.get(), &info) != SECSuccess) |
| 75 return ErrorRsaKeyImportNotSupported(); | 75 return ErrorRsaPrivateKeyImportNotSupported(); |
| 76 | 76 |
| 77 // CK_SLOT_INFO.hardwareVersion contains the major.minor | 77 // CK_SLOT_INFO.hardwareVersion contains the major.minor |
| 78 // version info for Softoken in the corresponding .major/.minor | 78 // version info for Softoken in the corresponding .major/.minor |
| 79 // fields, and .firmwareVersion contains the patch.build | 79 // fields, and .firmwareVersion contains the patch.build |
| 80 // version info (in the .major/.minor fields) | 80 // version info (in the .major/.minor fields) |
| 81 if ((info.hardwareVersion.major > 3) || | 81 if ((info.hardwareVersion.major > 3) || |
| 82 (info.hardwareVersion.major == 3 && | 82 (info.hardwareVersion.major == 3 && |
| 83 (info.hardwareVersion.minor > 16 || | 83 (info.hardwareVersion.minor > 16 || |
| 84 (info.hardwareVersion.minor == 16 && | 84 (info.hardwareVersion.minor == 16 && |
| 85 info.firmwareVersion.major >= 2)))) { | 85 info.firmwareVersion.major >= 2)))) { |
| 86 return Status::Success(); | 86 return Status::Success(); |
| 87 } | 87 } |
| 88 | 88 |
| 89 return ErrorRsaKeyImportNotSupported(); | 89 return ErrorRsaPrivateKeyImportNotSupported(); |
| 90 } | 90 } |
| 91 #else | 91 #else |
| 92 Status NssSupportsRsaKeyImport() { | 92 Status NssSupportsRsaPrivateKeyImport() { |
| 93 return Status::Success(); | 93 return Status::Success(); |
| 94 } | 94 } |
| 95 #endif | 95 #endif |
| 96 | 96 |
| 97 bool CreateRsaHashedPublicKeyAlgorithm( | 97 bool CreateRsaHashedPublicKeyAlgorithm( |
| 98 const blink::WebCryptoAlgorithm& algorithm, | 98 const blink::WebCryptoAlgorithm& algorithm, |
| 99 SECKEYPublicKey* key, | 99 SECKEYPublicKey* key, |
| 100 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 100 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
| 101 // TODO(eroman): What about other key types rsaPss, rsaOaep. | 101 // TODO(eroman): What about other key types rsaPss, rsaOaep. |
| 102 if (!key || key->keyType != rsaKey) | 102 if (!key || key->keyType != rsaKey) |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 | 339 |
| 340 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); | 340 buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len); |
| 341 return Status::Success(); | 341 return Status::Success(); |
| 342 } | 342 } |
| 343 | 343 |
| 344 Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm, | 344 Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm, |
| 345 bool extractable, | 345 bool extractable, |
| 346 blink::WebCryptoKeyUsageMask usage_mask, | 346 blink::WebCryptoKeyUsageMask usage_mask, |
| 347 const JwkRsaInfo& params, | 347 const JwkRsaInfo& params, |
| 348 blink::WebCryptoKey* key) { | 348 blink::WebCryptoKey* key) { |
| 349 Status status = NssSupportsRsaKeyImport(); | 349 Status status = NssSupportsRsaPrivateKeyImport(); |
| 350 if (status.IsError()) | 350 if (status.IsError()) |
| 351 return status; | 351 return status; |
| 352 | 352 |
| 353 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; | 353 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; |
| 354 CK_KEY_TYPE key_type = CKK_RSA; | 354 CK_KEY_TYPE key_type = CKK_RSA; |
| 355 CK_BBOOL ck_false = CK_FALSE; | 355 CK_BBOOL ck_false = CK_FALSE; |
| 356 | 356 |
| 357 std::vector<CK_ATTRIBUTE> key_template; | 357 std::vector<CK_ATTRIBUTE> key_template; |
| 358 | 358 |
| 359 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); | 359 AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 return Status::ErrorUnsupportedImportKeyFormat(); | 642 return Status::ErrorUnsupportedImportKeyFormat(); |
| 643 } | 643 } |
| 644 } | 644 } |
| 645 | 645 |
| 646 Status RsaHashedAlgorithm::ImportKeyPkcs8( | 646 Status RsaHashedAlgorithm::ImportKeyPkcs8( |
| 647 const CryptoData& key_data, | 647 const CryptoData& key_data, |
| 648 const blink::WebCryptoAlgorithm& algorithm, | 648 const blink::WebCryptoAlgorithm& algorithm, |
| 649 bool extractable, | 649 bool extractable, |
| 650 blink::WebCryptoKeyUsageMask usage_mask, | 650 blink::WebCryptoKeyUsageMask usage_mask, |
| 651 blink::WebCryptoKey* key) const { | 651 blink::WebCryptoKey* key) const { |
| 652 Status status = NssSupportsRsaKeyImport(); | 652 Status status = NssSupportsRsaPrivateKeyImport(); |
| 653 if (status.IsError()) | 653 if (status.IsError()) |
| 654 return status; | 654 return status; |
| 655 | 655 |
| 656 if (!key_data.byte_length()) | 656 if (!key_data.byte_length()) |
| 657 return Status::ErrorImportEmptyKeyData(); | 657 return Status::ErrorImportEmptyKeyData(); |
| 658 | 658 |
| 659 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 | 659 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8 |
| 660 // private key info object. | 660 // private key info object. |
| 661 SECItem pki_der = MakeSECItemForBuffer(key_data); | 661 SECItem pki_der = MakeSECItemForBuffer(key_data); |
| 662 | 662 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 | 702 |
| 703 return Status::Success(); | 703 return Status::Success(); |
| 704 } | 704 } |
| 705 | 705 |
| 706 Status RsaHashedAlgorithm::ImportKeySpki( | 706 Status RsaHashedAlgorithm::ImportKeySpki( |
| 707 const CryptoData& key_data, | 707 const CryptoData& key_data, |
| 708 const blink::WebCryptoAlgorithm& algorithm, | 708 const blink::WebCryptoAlgorithm& algorithm, |
| 709 bool extractable, | 709 bool extractable, |
| 710 blink::WebCryptoKeyUsageMask usage_mask, | 710 blink::WebCryptoKeyUsageMask usage_mask, |
| 711 blink::WebCryptoKey* key) const { | 711 blink::WebCryptoKey* key) const { |
| 712 Status status = NssSupportsRsaKeyImport(); | |
| 713 if (status.IsError()) | |
| 714 return status; | |
| 715 | |
| 716 if (!key_data.byte_length()) | 712 if (!key_data.byte_length()) |
| 717 return Status::ErrorImportEmptyKeyData(); | 713 return Status::ErrorImportEmptyKeyData(); |
| 718 | 714 |
| 719 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject | 715 // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject |
| 720 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. | 716 // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo. |
| 721 SECItem spki_item = MakeSECItemForBuffer(key_data); | 717 SECItem spki_item = MakeSECItemForBuffer(key_data); |
| 722 const ScopedCERTSubjectPublicKeyInfo spki( | 718 const ScopedCERTSubjectPublicKeyInfo spki( |
| 723 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); | 719 SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item)); |
| 724 if (!spki) | 720 if (!spki) |
| 725 return Status::DataError(); | 721 return Status::DataError(); |
| 726 | 722 |
| 727 crypto::ScopedSECKEYPublicKey sec_public_key( | 723 crypto::ScopedSECKEYPublicKey sec_public_key( |
| 728 SECKEY_ExtractPublicKey(spki.get())); | 724 SECKEY_ExtractPublicKey(spki.get())); |
| 729 if (!sec_public_key) | 725 if (!sec_public_key) |
| 730 return Status::DataError(); | 726 return Status::DataError(); |
| 731 | 727 |
| 732 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 728 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
| 733 if (sec_key_type != rsaKey) | 729 if (sec_key_type != rsaKey) |
| 734 return Status::DataError(); | 730 return Status::DataError(); |
| 735 | 731 |
| 736 blink::WebCryptoKeyAlgorithm key_algorithm; | 732 blink::WebCryptoKeyAlgorithm key_algorithm; |
| 737 if (!CreateRsaHashedPublicKeyAlgorithm( | 733 if (!CreateRsaHashedPublicKeyAlgorithm( |
| 738 algorithm, sec_public_key.get(), &key_algorithm)) | 734 algorithm, sec_public_key.get(), &key_algorithm)) |
| 739 return Status::ErrorUnexpected(); | 735 return Status::ErrorUnexpected(); |
| 740 | 736 |
| 741 // TODO(eroman): This is probably going to be the same as the input. | 737 // TODO(eroman): This is probably going to be the same as the input. |
| 742 std::vector<uint8_t> spki_data; | 738 std::vector<uint8_t> spki_data; |
| 743 status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); | 739 Status status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); |
| 744 if (status.IsError()) | 740 if (status.IsError()) |
| 745 return status; | 741 return status; |
| 746 | 742 |
| 747 scoped_ptr<PublicKeyNss> key_handle( | 743 scoped_ptr<PublicKeyNss> key_handle( |
| 748 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); | 744 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); |
| 749 | 745 |
| 750 *key = blink::WebCryptoKey::create(key_handle.release(), | 746 *key = blink::WebCryptoKey::create(key_handle.release(), |
| 751 blink::WebCryptoKeyTypePublic, | 747 blink::WebCryptoKeyTypePublic, |
| 752 extractable, | 748 extractable, |
| 753 key_algorithm, | 749 key_algorithm, |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 return Status::Success(); | 851 return Status::Success(); |
| 856 } | 852 } |
| 857 default: | 853 default: |
| 858 return Status::ErrorUnexpected(); | 854 return Status::ErrorUnexpected(); |
| 859 } | 855 } |
| 860 } | 856 } |
| 861 | 857 |
| 862 } // namespace webcrypto | 858 } // namespace webcrypto |
| 863 | 859 |
| 864 } // namespace content | 860 } // namespace content |
| OLD | NEW |