diff options
-rw-r--r-- | chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc | 42 | ||||
-rw-r--r-- | chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc | 22 | ||||
-rw-r--r-- | chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h | 4 | ||||
-rw-r--r-- | chrome/browser/chromeos/platform_keys/platform_keys_nss.cc | 42 | ||||
-rw-r--r-- | components/ownership.gypi | 5 | ||||
-rw-r--r-- | components/ownership/BUILD.gn | 5 | ||||
-rw-r--r-- | components/ownership/owner_key_util_impl.cc | 21 | ||||
-rw-r--r-- | crypto/BUILD.gn | 23 | ||||
-rw-r--r-- | crypto/crypto.gyp | 16 | ||||
-rw-r--r-- | crypto/crypto.gypi | 2 | ||||
-rw-r--r-- | crypto/nss_key_util.cc | 163 | ||||
-rw-r--r-- | crypto/nss_key_util.h | 58 | ||||
-rw-r--r-- | crypto/nss_key_util_unittest.cc | 87 | ||||
-rw-r--r-- | crypto/rsa_private_key.h | 69 | ||||
-rw-r--r-- | crypto/rsa_private_key_nss.cc | 233 | ||||
-rw-r--r-- | crypto/rsa_private_key_nss_unittest.cc | 66 | ||||
-rw-r--r-- | net/net.gyp | 1 | ||||
-rw-r--r-- | net/test/cert_test_util.h | 15 | ||||
-rw-r--r-- | net/test/cert_test_util_nss.cc | 29 |
20 files changed, 478 insertions, 434 deletions
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc index 2607ace..c96e922 100644 --- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc @@ -45,6 +45,7 @@ #include "components/ownership/mock_owner_key_util.h" #include "components/user_manager/fake_user_manager.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "crypto/nss_key_util.h" #include "crypto/nss_util_internal.h" #include "crypto/scoped_test_nss_chromeos_user.h" #include "google_apis/gaia/mock_url_fetcher_factory.h" @@ -118,11 +119,11 @@ std::vector<uint8> GetOwnerPublicKey() { kOwnerPublicKey + arraysize(kOwnerPublicKey)); } -scoped_ptr<crypto::RSAPrivateKey> CreateOwnerKeyInSlot(PK11SlotInfo* slot) { +bool CreateOwnerKeyInSlot(PK11SlotInfo* slot) { const std::vector<uint8> key(kOwnerPrivateKey, kOwnerPrivateKey + arraysize(kOwnerPrivateKey)); - return make_scoped_ptr( - crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot, key)); + return crypto::ImportNSSKeyFromPrivateKeyInfo(slot, key, + true /* permanent */); } } // namespace @@ -472,7 +473,7 @@ TEST_F(CryptohomeAuthenticatorTest, ResolveOwnerNeededSuccess) { crypto::ScopedPK11Slot user_slot( crypto::GetPublicSlotForChromeOSUser(user_context_.GetUserIDHash())); - CreateOwnerKeyInSlot(user_slot.get()); + ASSERT_TRUE(CreateOwnerKeyInSlot(user_slot.get())); profile_manager_.reset( new TestingProfileManager(TestingBrowserProcess::GetGlobal())); diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc index 3321ed9..46058c1 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc @@ -5,6 +5,7 @@ #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h" #include <cryptohi.h> +#include <keyhi.h> #include "base/base64.h" #include "base/bind.h" @@ -22,8 +23,8 @@ #include "chrome/browser/browser_process.h" #include "chrome/common/pref_names.h" #include "content/public/browser/browser_thread.h" +#include "crypto/nss_key_util.h" #include "crypto/nss_util_internal.h" -#include "crypto/rsa_private_key.h" #include "crypto/scoped_nss_types.h" namespace { @@ -57,7 +58,7 @@ void GetSystemSlotOnIOThread( // Checks if a private RSA key associated with |public_key| can be found in // |slot|. // Must be called on a worker thread. -scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( +crypto::ScopedSECKEYPrivateKey GetPrivateKeyOnWorkerThread( PK11SlotInfo* slot, const std::string& public_key) { const uint8* public_key_uint8 = @@ -65,10 +66,14 @@ scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( std::vector<uint8> public_key_vector( public_key_uint8, public_key_uint8 + public_key.size()); - scoped_ptr<crypto::RSAPrivateKey> rsa_key( - crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); - if (!rsa_key || rsa_key->key()->pkcs11Slot != slot) - return scoped_ptr<crypto::RSAPrivateKey>(); + // TODO(davidben): This should be equivalent to calling + // FindNSSKeyFromPublicKeyInfoInSlot. + crypto::ScopedSECKEYPrivateKey rsa_key( + crypto::FindNSSKeyFromPublicKeyInfo(public_key_vector)); + if (!rsa_key || rsa_key->pkcs11Slot != slot || + SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey) { + return nullptr; + } return rsa_key.Pass(); } @@ -81,7 +86,7 @@ void SignDataOnWorkerThread( const std::string& data, const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, const base::Callback<void(const std::string&)>& callback) { - scoped_ptr<crypto::RSAPrivateKey> private_key( + crypto::ScopedSECKEYPrivateKey private_key( GetPrivateKeyOnWorkerThread(slot.get(), public_key)); if (!private_key) { LOG(ERROR) << "Private key for signing data not found"; @@ -93,8 +98,7 @@ void SignDataOnWorkerThread( crypto::ScopedSECItem sign_result(SECITEM_AllocItem(NULL, NULL, 0)); if (SEC_SignData(sign_result.get(), reinterpret_cast<const unsigned char*>(data.data()), - data.size(), - private_key->key(), + data.size(), private_key.get(), SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION) != SECSuccess) { LOG(ERROR) << "Failed to sign data"; response_task_runner->PostTask(FROM_HERE, @@ -123,17 +127,20 @@ void CreateTpmKeyPairOnWorkerThread( return; } - scoped_ptr<crypto::RSAPrivateKey> rsa_key( - crypto::RSAPrivateKey::CreateSensitive(slot.get(), kKeyModulusLength)); - if (!rsa_key) { + crypto::ScopedSECKEYPublicKey public_key_obj; + crypto::ScopedSECKEYPrivateKey private_key_obj; + if (!crypto::GenerateRSAKeyPairNSS(slot.get(), kKeyModulusLength, + true /* permanent */, &public_key_obj, + &private_key_obj)) { LOG(ERROR) << "Failed to create an RSA key."; response_task_runner->PostTask(FROM_HERE, base::Bind(callback, std::string())); return; } - std::vector<uint8> created_public_key; - if (!rsa_key->ExportPublicKey(&created_public_key)) { + crypto::ScopedSECItem public_key_der( + SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_obj.get())); + if (!public_key_der) { LOG(ERROR) << "Failed to export public key."; response_task_runner->PostTask(FROM_HERE, base::Bind(callback, std::string())); @@ -141,10 +148,9 @@ void CreateTpmKeyPairOnWorkerThread( } response_task_runner->PostTask( - FROM_HERE, - base::Bind(callback, - std::string(created_public_key.begin(), - created_public_key.end()))); + FROM_HERE, base::Bind(callback, std::string(reinterpret_cast<const char*>( + public_key_der->data), + public_key_der->len))); } } // namespace diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc index a96f0aa..20fdd78 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc @@ -4,6 +4,8 @@ #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" +#include <keyhi.h> + #include <algorithm> #include <string> @@ -29,9 +31,9 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/common/content_switches.h" +#include "crypto/nss_key_util.h" #include "crypto/nss_util.h" #include "crypto/nss_util_internal.h" -#include "crypto/rsa_private_key.h" #include "crypto/scoped_nss_types.h" #include "crypto/signature_creator.h" @@ -72,9 +74,14 @@ void LoadPrivateKeyByPublicKey( crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser( username_hash, base::Callback<void(crypto::ScopedPK11Slot)>()); - // If private slot is already available, this will check it. If not, - // we'll get called again later when the TPM Token is ready, and the - // slot will be available then. + // If private slot is already available, this will check it. If not, we'll get + // called again later when the TPM Token is ready, and the slot will be + // available then. FindPrivateKeyInSlot internally checks for a null slot if + // needbe. + // + // TODO(davidben): The null check should be in the caller rather than + // internally in the OwnerKeyUtil implementation. The tests currently get a + // null private_slot and expect the mock OwnerKeyUtil to still be called. scoped_refptr<PrivateKey> private_key( new PrivateKey(owner_key_util->FindPrivateKeyInSlot(public_key->data(), private_slot.get()))); @@ -124,10 +131,9 @@ bool DoesPrivateKeyExistAsyncHelper( std::vector<uint8> public_key; if (!owner_key_util->ImportPublicKey(&public_key)) return false; - scoped_ptr<crypto::RSAPrivateKey> key( - crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); - bool is_owner = key.get() != NULL; - return is_owner; + crypto::ScopedSECKEYPrivateKey key = + crypto::FindNSSKeyFromPublicKeyInfo(public_key); + return key && SECKEY_GetPrivateKeyType(key.get()) == rsaKey; } // Checks whether NSS slots with private key are mounted or diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h index 354450b..aea7cc0 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h @@ -135,7 +135,9 @@ class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService, // OwnerSettingsService protected interface overrides: - // Reloads private key from profile's NSS slots, responds via |callback|. + // Reloads private key from profile's NSS slots, responds via |callback|. On + // success, |private_key| is non-null, but if the private key doesn't exist, + // |private_key->key()| may be null. void ReloadKeypairImpl(const base::Callback< void(const scoped_refptr<ownership::PublicKey>& public_key, const scoped_refptr<ownership::PrivateKey>& private_key)>& callback) diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc index af14d11..5678baf 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc +++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc @@ -31,7 +31,8 @@ #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" -#include "crypto/rsa_private_key.h" +#include "crypto/nss_key_util.h" +#include "crypto/scoped_nss_types.h" #include "net/base/crypto_module.h" #include "net/base/net_errors.h" #include "net/cert/cert_database.h" @@ -400,25 +401,34 @@ GetTokensState::GetTokensState(const GetTokensCallback& callback) // Does the actual key generation on a worker thread. Used by // GenerateRSAKeyWithDB(). void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { - scoped_ptr<crypto::RSAPrivateKey> rsa_key( - crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(), - state->modulus_length_bits_)); - if (!rsa_key) { + if (!state->slot_) { + LOG(ERROR) << "No slot."; + state->OnError(FROM_HERE, kErrorInternal); + return; + } + + crypto::ScopedSECKEYPublicKey public_key; + crypto::ScopedSECKEYPrivateKey private_key; + if (!crypto::GenerateRSAKeyPairNSS( + state->slot_.get(), state->modulus_length_bits_, true /* permanent */, + &public_key, &private_key)) { LOG(ERROR) << "Couldn't create key."; state->OnError(FROM_HERE, kErrorInternal); return; } - std::vector<uint8> public_key_spki_der; - if (!rsa_key->ExportPublicKey(&public_key_spki_der)) { - // TODO(pneubeck): Remove rsa_key from storage. + crypto::ScopedSECItem public_key_der( + SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); + if (!public_key_der) { + // TODO(pneubeck): Remove private_key and public_key from storage. LOG(ERROR) << "Couldn't export public key."; state->OnError(FROM_HERE, kErrorInternal); return; } state->CallBack( FROM_HERE, - std::string(public_key_spki_der.begin(), public_key_spki_der.end()), + std::string(reinterpret_cast<const char*>(public_key_der->data), + public_key_der->len), std::string() /* no error */); } @@ -442,13 +452,13 @@ void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { public_key_uint8, public_key_uint8 + state->public_key_.size()); // TODO(pneubeck): This searches all slots. Change to look only at |slot_|. - scoped_ptr<crypto::RSAPrivateKey> rsa_key( - crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key_vector)); + crypto::ScopedSECKEYPrivateKey rsa_key( + crypto::FindNSSKeyFromPublicKeyInfo(public_key_vector)); // Fail if the key was not found. If a specific slot was requested, also fail // if the key was found in the wrong slot. - if (!rsa_key || - (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { + if (!rsa_key || SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey || + (state->slot_ && rsa_key->pkcs11Slot != state->slot_)) { state->OnError(FROM_HERE, kErrorKeyNotFound); return; } @@ -464,7 +474,7 @@ void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { state->data_.size()}; // Compute signature of hash. - int signature_len = PK11_SignatureLen(rsa_key->key()); + int signature_len = PK11_SignatureLen(rsa_key.get()); if (signature_len <= 0) { state->OnError(FROM_HERE, kErrorInternal); return; @@ -473,7 +483,7 @@ void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { std::vector<unsigned char> signature(signature_len); SECItem signature_output = { siBuffer, vector_as_array(&signature), signature.size()}; - if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) + if (PK11_Sign(rsa_key.get(), &signature_output, &input) == SECSuccess) signature_str.assign(signature.begin(), signature.end()); } else { SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; @@ -499,7 +509,7 @@ void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { if (SEC_SignData( &sign_result, reinterpret_cast<const unsigned char*>(state->data_.data()), - state->data_.size(), rsa_key->key(), sign_alg_tag) == SECSuccess) { + state->data_.size(), rsa_key.get(), sign_alg_tag) == SECSuccess) { signature_str.assign(sign_result.data, sign_result.data + sign_result.len); } diff --git a/components/ownership.gypi b/components/ownership.gypi index 0b95fe2..4784259 100644 --- a/components/ownership.gypi +++ b/components/ownership.gypi @@ -35,6 +35,11 @@ '<(DEPTH)/components/components.gyp:policy', ], }], + ['use_nss_certs==1', { + 'dependencies': [ + '../build/linux/system.gyp:ssl', + ], + }], ], }], } diff --git a/components/ownership/BUILD.gn b/components/ownership/BUILD.gn index 1bca927..cdaf227 100644 --- a/components/ownership/BUILD.gn +++ b/components/ownership/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/crypto.gni") import("//build/config/features.gni") component("ownership") { @@ -29,6 +30,10 @@ component("ownership") { if (enable_configuration_policy) { deps += [ "//components/policy" ] } + + if (use_nss_certs) { + deps += [ "//crypto:platform" ] + } } source_set("unit_tests") { diff --git a/components/ownership/owner_key_util_impl.cc b/components/ownership/owner_key_util_impl.cc index bc7208e..5a400d5 100644 --- a/components/ownership/owner_key_util_impl.cc +++ b/components/ownership/owner_key_util_impl.cc @@ -8,7 +8,12 @@ #include "base/files/file_util.h" #include "base/logging.h" + +#if defined(USE_NSS_CERTS) +#include <keythi.h> +#include "crypto/nss_key_util.h" #include "crypto/rsa_private_key.h" +#endif namespace ownership { @@ -54,7 +59,21 @@ bool OwnerKeyUtilImpl::ImportPublicKey(std::vector<uint8>* output) { crypto::RSAPrivateKey* OwnerKeyUtilImpl::FindPrivateKeyInSlot( const std::vector<uint8>& key, PK11SlotInfo* slot) { - return crypto::RSAPrivateKey::FindFromPublicKeyInfoInSlot(key, slot); + if (!slot) + return nullptr; + + crypto::ScopedSECKEYPrivateKey private_key( + crypto::FindNSSKeyFromPublicKeyInfoInSlot(key, slot)); + if (!private_key || SECKEY_GetPrivateKeyType(private_key.get()) != rsaKey) + return nullptr; +#if defined(USE_OPENSSL) + // TODO(davidben): This assumes that crypto::RSAPrivateKey also uses NSS. + // https://crbug.com/478777 + NOTIMPLEMENTED(); + return nullptr; +#else + return crypto::RSAPrivateKey::CreateFromKey(private_key.get()); +#endif } #endif // defined(USE_NSS_CERTS) diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn index c1eabe6..f84c4d4 100644 --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn @@ -50,6 +50,8 @@ component("crypto") { "mock_apple_keychain.h", "mock_apple_keychain_ios.cc", "mock_apple_keychain_mac.cc", + "nss_key_util.cc", + "nss_key_util.h", "nss_util.cc", "nss_util.h", "nss_util_internal.h", @@ -171,10 +173,12 @@ component("crypto") { ] } - # Remove nss_util when NSS is used for neither the internal crypto library - # nor the platform certificate library. + # Some files are built when NSS is used at all, either for the internal crypto + # library or the platform certificate library. if (use_openssl && !use_nss_certs) { sources -= [ + "nss_key_util.cc", + "nss_key_util.h", "nss_util.cc", "nss_util.h", "nss_util_internal.h", @@ -226,12 +230,12 @@ test("crypto_unittests") { "ghash_unittest.cc", "hkdf_unittest.cc", "hmac_unittest.cc", + "nss_key_util_unittest.cc", "nss_util_unittest.cc", "openssl_bio_string_unittest.cc", "p224_spake_unittest.cc", "p224_unittest.cc", "random_unittest.cc", - "rsa_private_key_nss_unittest.cc", "rsa_private_key_unittest.cc", "secure_hash_unittest.cc", "sha2_unittest.cc", @@ -240,15 +244,16 @@ test("crypto_unittests") { "symmetric_key_unittest.cc", ] - # Remove nss_util when NSS is used for neither the internal crypto library - # nor the platform certificate library. + # Some files are built when NSS is used at all, either for the internal crypto + # library or the platform certificate library. if (use_openssl && !use_nss_certs) { - sources -= [ "nss_util_unittest.cc" ] + sources -= [ + "nss_key_util_unittest.cc", + "nss_util_unittest.cc", + ] } - if (use_openssl) { - sources -= [ "rsa_private_key_nss_unittest.cc" ] - } else { + if (!use_openssl) { sources -= [ "openssl_bio_string_unittest.cc" ] } diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index 00b59b5..e6bff0b 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -143,9 +143,11 @@ ], },], [ 'use_openssl==1 and use_nss_certs==0', { - # NSS is used for neither the internal crypto library nor the - # platform certificate library. + # Some files are built when NSS is used at all, either for the + # internal crypto library or the platform certificate library. 'sources!': [ + 'nss_key_util.cc', + 'nss_key_util.h', 'nss_util.cc', 'nss_util.h', 'nss_util_internal.h', @@ -168,13 +170,13 @@ 'ghash_unittest.cc', 'hkdf_unittest.cc', 'hmac_unittest.cc', + 'nss_key_util_unittest.cc', 'nss_util_unittest.cc', 'openssl_bio_string_unittest.cc', 'p224_unittest.cc', 'p224_spake_unittest.cc', 'random_unittest.cc', 'rsa_private_key_unittest.cc', - 'rsa_private_key_nss_unittest.cc', 'secure_hash_unittest.cc', 'sha2_unittest.cc', 'signature_creator_unittest.cc', @@ -205,9 +207,10 @@ ], }], [ 'use_openssl == 1 and use_nss_certs == 0', { - # nss_util is built if NSS is used for either the internal crypto - # library or the platform certificate library. + # Some files are built when NSS is used at all, either for the + # internal crypto library or the platform certificate library. 'sources!': [ + 'nss_key_util_unittest.cc', 'nss_util_unittest.cc', ], }], @@ -224,9 +227,6 @@ 'dependencies': [ '../third_party/boringssl/boringssl.gyp:boringssl', ], - 'sources!': [ - 'rsa_private_key_nss_unittest.cc', - ], }, { 'sources!': [ 'openssl_bio_string_unittest.cc', diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi index 4456b10..73b3332 100644 --- a/crypto/crypto.gypi +++ b/crypto/crypto.gypi @@ -67,6 +67,8 @@ 'p224_spake.cc', 'p224_spake.h', 'nss_crypto_module_delegate.h', + 'nss_key_util.cc', + 'nss_key_util.h', 'nss_util.cc', 'nss_util.h', 'nss_util_internal.h', diff --git a/crypto/nss_key_util.cc b/crypto/nss_key_util.cc new file mode 100644 index 0000000..77435fb --- /dev/null +++ b/crypto/nss_key_util.cc @@ -0,0 +1,163 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_key_util.h" + +#include <cryptohi.h> +#include <keyhi.h> +#include <pk11pub.h> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "crypto/nss_util.h" + +#if defined(USE_NSS_CERTS) +#include <secmod.h> +#include "crypto/nss_util_internal.h" +#endif + +namespace crypto { + +namespace { + +#if defined(USE_NSS_CERTS) + +struct PublicKeyInfoDeleter { + inline void operator()(CERTSubjectPublicKeyInfo* spki) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + } +}; + +typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter> + ScopedPublicKeyInfo; + +// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing +// the CKA_ID of that public key or nullptr on error. +ScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t>& input) { + // First, decode and save the public key. + SECItem key_der; + key_der.type = siBuffer; + key_der.data = const_cast<unsigned char*>(vector_as_array(&input)); + key_der.len = input.size(); + + ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); + if (!spki) + return nullptr; + + ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); + if (!result) + return nullptr; + + // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are + // supported. + if (SECKEY_GetPublicKeyType(result.get()) != rsaKey) + return nullptr; + + return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus)); +} + +#endif // defined(USE_NSS_CERTS) + +} // namespace + +bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot, + uint16_t num_bits, + bool permanent, + ScopedSECKEYPublicKey* public_key, + ScopedSECKEYPrivateKey* private_key) { + DCHECK(slot); + + PK11RSAGenParams param; + param.keySizeInBits = num_bits; + param.pe = 65537L; + SECKEYPublicKey* public_key_raw = nullptr; + private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + ¶m, &public_key_raw, permanent, + permanent /* sensitive */, nullptr)); + if (!*private_key) + return false; + + public_key->reset(public_key_raw); + return true; +} + +ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo( + PK11SlotInfo* slot, + const std::vector<uint8_t>& input, + bool permanent) { + DCHECK(slot); + + ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + DCHECK(arena); + + // Excess data is illegal, but NSS silently accepts it, so first ensure that + // |input| consists of a single ASN.1 element. + SECItem input_item; + input_item.data = const_cast<unsigned char*>(vector_as_array(&input)); + input_item.len = input.size(); + SECItem der_private_key_info; + SECStatus rv = + SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, + SEC_ASN1_GET(SEC_AnyTemplate), &input_item); + if (rv != SECSuccess) + return nullptr; + + // Allow the private key to be used for key unwrapping, data decryption, + // and signature generation. + const unsigned int key_usage = + KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; + SECKEYPrivateKey* key_raw = nullptr; + rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot, &der_private_key_info, nullptr, nullptr, permanent, + permanent /* sensitive */, key_usage, &key_raw, nullptr); + if (rv != SECSuccess) + return nullptr; + return ScopedSECKEYPrivateKey(key_raw); +} + +#if defined(USE_NSS_CERTS) + +ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( + const std::vector<uint8_t>& input) { + EnsureNSSInit(); + + ScopedSECItem cka_id(MakeIDFromSPKI(input)); + if (!cka_id) + return nullptr; + + // Search all slots in all modules for the key with the given ID. + AutoSECMODListReadLock auto_lock; + const SECMODModuleList* head = SECMOD_GetDefaultModuleList(); + for (const SECMODModuleList* item = head; item != nullptr; + item = item->next) { + int slot_count = item->module->loaded ? item->module->slotCount : 0; + for (int i = 0; i < slot_count; i++) { + // Look for the key in slot |i|. + ScopedSECKEYPrivateKey key( + PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); + if (key) + return key.Pass(); + } + } + + // The key wasn't found in any module. + return nullptr; +} + +ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot( + const std::vector<uint8_t>& input, + PK11SlotInfo* slot) { + DCHECK(slot); + + ScopedSECItem cka_id(MakeIDFromSPKI(input)); + if (!cka_id) + return nullptr; + + return ScopedSECKEYPrivateKey( + PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr)); +} + +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto diff --git a/crypto/nss_key_util.h b/crypto/nss_key_util.h new file mode 100644 index 0000000..12b948d --- /dev/null +++ b/crypto/nss_key_util.h @@ -0,0 +1,58 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_NSS_KEY_UTIL_H_ +#define CRYPTO_NSS_KEY_UTIL_H_ + +#include <stdint.h> + +#include <vector> + +#include "build/build_config.h" +#include "crypto/crypto_export.h" +#include "crypto/scoped_nss_types.h" + +typedef struct PK11SlotInfoStr PK11SlotInfo; + +namespace crypto { + +// Generates a new RSA keypair of size |num_bits| in |slot|. Returns true on +// success and false on failure. If |permanent| is true, the resulting key is +// permanent and is not exportable in plaintext form. +CRYPTO_EXPORT bool GenerateRSAKeyPairNSS( + PK11SlotInfo* slot, + uint16_t num_bits, + bool permanent, + ScopedSECKEYPublicKey* out_public_key, + ScopedSECKEYPrivateKey* out_private_key); + +// Imports a private key from |input| into |slot|. |input| is interpreted as a +// DER-encoded PrivateKeyInfo block from PKCS #8. Returns nullptr on error. If +// |permanent| is true, the resulting key is permanent and is not exportable in +// plaintext form. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +ImportNSSKeyFromPrivateKeyInfo(PK11SlotInfo* slot, + const std::vector<uint8_t>& input, + bool permanent); + +#if defined(USE_NSS_CERTS) + +// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for +// the private key half in the key database. Returns the private key on success +// or nullptr on error. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +FindNSSKeyFromPublicKeyInfo(const std::vector<uint8_t>& input); + +// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for +// the private key half in the slot specified by |slot|. Returns the private key +// on success or nullptr on error. +CRYPTO_EXPORT ScopedSECKEYPrivateKey +FindNSSKeyFromPublicKeyInfoInSlot(const std::vector<uint8_t>& input, + PK11SlotInfo* slot); + +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto + +#endif // CRYPTO_NSS_KEY_UTIL_H_ diff --git a/crypto/nss_key_util_unittest.cc b/crypto/nss_key_util_unittest.cc new file mode 100644 index 0000000..f8de8e2 --- /dev/null +++ b/crypto/nss_key_util_unittest.cc @@ -0,0 +1,87 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/nss_key_util.h" + +#include <keyhi.h> +#include <pk11pub.h> + +#include <vector> + +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crypto { + +class NSSKeyUtilTest : public testing::Test { + public: + void SetUp() override { + EnsureNSSInit(); + + internal_slot_.reset(PK11_GetInternalSlot()); + ASSERT_TRUE(internal_slot_); + } + + PK11SlotInfo* internal_slot() { return internal_slot_.get(); } + + private: + ScopedPK11Slot internal_slot_; +}; + +TEST_F(NSSKeyUtilTest, GenerateRSAKeyPairNSS) { + const int kKeySizeBits = 1024; + + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), kKeySizeBits, + false /* not permanent */, &public_key, + &private_key)); + + EXPECT_EQ(rsaKey, SECKEY_GetPublicKeyType(public_key.get())); + EXPECT_EQ(rsaKey, SECKEY_GetPrivateKeyType(private_key.get())); + EXPECT_EQ((kKeySizeBits + 7) / 8, + PK11_GetPrivateModulusLen(private_key.get())); +} + +#if defined(USE_NSS_CERTS) +TEST_F(NSSKeyUtilTest, FindNSSKeyFromPublicKeyInfo) { + // Create an NSS keypair, which will put the keys in the user's NSSDB. + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 256, + false /* not permanent */, &public_key, + &private_key)); + + ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); + ASSERT_TRUE(item); + std::vector<uint8_t> public_key_der(item->data, item->data + item->len); + + ScopedSECKEYPrivateKey private_key2 = + FindNSSKeyFromPublicKeyInfo(public_key_der); + ASSERT_TRUE(private_key2); + EXPECT_EQ(private_key->pkcs11ID, private_key2->pkcs11ID); +} + +TEST_F(NSSKeyUtilTest, FailedFindNSSKeyFromPublicKeyInfo) { + // Create an NSS keypair, which will put the keys in the user's NSSDB. + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 256, + false /* not permanent */, &public_key, + &private_key)); + + ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); + ASSERT_TRUE(item); + std::vector<uint8_t> public_key_der(item->data, item->data + item->len); + + // Remove the keys from the DB, and make sure we can't find them again. + PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID); + PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID); + + EXPECT_FALSE(FindNSSKeyFromPublicKeyInfo(public_key_der)); +} +#endif // defined(USE_NSS_CERTS) + +} // namespace crypto diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h index 9ab9c57..637be38 100644 --- a/crypto/rsa_private_key.h +++ b/crypto/rsa_private_key.h @@ -191,44 +191,6 @@ class CRYPTO_EXPORT RSAPrivateKey { static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key); #endif - // TODO(davidben): These functions are used when NSS is the platform key - // store, but they also assume that the internal crypto library is NSS. Split - // out the convenience NSS platform key methods from the logic which expects - // an RSAPrivateKey. See https://crbug.com/478777. -#if defined(USE_NSS_CERTS) && !defined(USE_OPENSSL) - // Create a new random instance in |slot|. Can return NULL if initialization - // fails. The created key is permanent and is not exportable in plaintext - // form. - static RSAPrivateKey* CreateSensitive(PK11SlotInfo* slot, uint16 num_bits); - - // Create a new instance in |slot| by importing an existing private key. The - // format is an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can - // return NULL if initialization fails. - // The created key is permanent and is not exportable in plaintext form. - static RSAPrivateKey* CreateSensitiveFromPrivateKeyInfo( - PK11SlotInfo* slot, - const std::vector<uint8>& input); - - // Import an existing public key, and then search for the private - // half in the key database. The format of the public key blob is is - // an X509 SubjectPublicKeyInfo block. This can return NULL if - // initialization fails or the private key cannot be found. The - // caller takes ownership of the returned object, but nothing new is - // created in the key database. - static RSAPrivateKey* FindFromPublicKeyInfo( - const std::vector<uint8>& input); - - // Import an existing public key, and then search for the private - // half in the slot specified by |slot|. The format of the public - // key blob is is an X509 SubjectPublicKeyInfo block. This can return - // NULL if initialization fails or the private key cannot be found. - // The caller takes ownership of the returned object, but nothing new - // is created in the slot. - static RSAPrivateKey* FindFromPublicKeyInfoInSlot( - const std::vector<uint8>& input, - PK11SlotInfo* slot); -#endif // USE_NSS_CERTS && !USE_OPENSSL - #if defined(USE_OPENSSL) EVP_PKEY* key() { return key_; } #else @@ -251,38 +213,9 @@ class CRYPTO_EXPORT RSAPrivateKey { FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); #endif - // Constructor is private. Use one of the Create*() or Find*() - // methods above instead. + // Constructor is private. Use one of the Create*() methods above instead. RSAPrivateKey(); -#if !defined(USE_OPENSSL) - // Shared helper for Create() and CreateSensitive(). - // TODO(cmasone): consider replacing |permanent| and |sensitive| with a - // flags arg created by ORing together some enumerated values. - // Note: |permanent| is only supported when USE_NSS_CERTS is defined. - static RSAPrivateKey* CreateWithParams(PK11SlotInfo* slot, - uint16 num_bits, - bool permanent, - bool sensitive); - - // Shared helper for CreateFromPrivateKeyInfo() and - // CreateSensitiveFromPrivateKeyInfo(). - // Note: |permanent| is only supported when USE_NSS_CERTS is defined. - static RSAPrivateKey* CreateFromPrivateKeyInfoWithParams( - PK11SlotInfo* slot, - const std::vector<uint8>& input, - bool permanent, - bool sensitive); -#endif - -#if defined(USE_NSS_CERTS) - // Import an existing public key. The format of the public key blob - // is an X509 SubjectPublicKeyInfo block. This can return NULL if - // initialization fails. The caller takes ownership of the returned - // object. Note that this method doesn't initialize the |key_| member. - static RSAPrivateKey* InitPublicPart(const std::vector<uint8>& input); -#endif - #if defined(USE_OPENSSL) EVP_PKEY* key_; #else diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc index c9e6a87..88e55fa 100644 --- a/crypto/rsa_private_key_nss.cc +++ b/crypto/rsa_private_key_nss.cc @@ -7,7 +7,6 @@ #include <cryptohi.h> #include <keyhi.h> #include <pk11pub.h> -#include <secmod.h> #include <list> @@ -15,8 +14,8 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_util.h" +#include "crypto/nss_key_util.h" #include "crypto/nss_util.h" -#include "crypto/nss_util_internal.h" #include "crypto/scoped_nss_types.h" // TODO(rafaelw): Consider using NSS's ASN.1 encoder. @@ -38,37 +37,6 @@ static bool ReadAttribute(SECKEYPrivateKey* key, return true; } -#if defined(USE_NSS_CERTS) -struct PublicKeyInfoDeleter { - inline void operator()(CERTSubjectPublicKeyInfo* spki) { - SECKEY_DestroySubjectPublicKeyInfo(spki); - } -}; - -typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter> - ScopedPublicKeyInfo; - -// The function decodes RSA public key from the |input|. -crypto::ScopedSECKEYPublicKey GetRSAPublicKey(const std::vector<uint8>& input) { - // First, decode and save the public key. - SECItem key_der; - key_der.type = siBuffer; - key_der.data = const_cast<unsigned char*>(&input[0]); - key_der.len = input.size(); - - ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); - if (!spki) - return crypto::ScopedSECKEYPublicKey(); - - crypto::ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); - - // Make sure the key is an RSA key.. If not, that's an error. - if (!result || result->keyType != rsaKey) - return crypto::ScopedSECKEYPublicKey(); - return result.Pass(); -} -#endif // defined(USE_NSS_CERTS) - } // namespace namespace crypto { @@ -85,10 +53,22 @@ RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { EnsureNSSInit(); ScopedPK11Slot slot(PK11_GetInternalSlot()); - return CreateWithParams(slot.get(), - num_bits, - false /* not permanent */, - false /* not sensitive */); + if (!slot) { + NOTREACHED(); + return nullptr; + } + + ScopedSECKEYPublicKey public_key; + ScopedSECKEYPrivateKey private_key; + if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */, + &public_key, &private_key)) { + return nullptr; + } + + RSAPrivateKey* rsa_key = new RSAPrivateKey; + rsa_key->public_key_ = public_key.release(); + rsa_key->key_ = private_key.release(); + return rsa_key; } // static @@ -97,11 +77,15 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( EnsureNSSInit(); ScopedPK11Slot slot(PK11_GetInternalSlot()); - return CreateFromPrivateKeyInfoWithParams( - slot.get(), - input, - false /* not permanent */, - false /* not sensitive */); + if (!slot) { + NOTREACHED(); + return nullptr; + } + ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo( + slot.get(), input, false /* not permanent */)); + if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey) + return nullptr; + return RSAPrivateKey::CreateFromKey(key.get()); } // static @@ -120,83 +104,6 @@ RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) { return copy; } -#if defined(USE_NSS_CERTS) -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitive(PK11SlotInfo* slot, - uint16 num_bits) { - return CreateWithParams(slot, - num_bits, - true /* permanent */, - true /* sensitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( - PK11SlotInfo* slot, - const std::vector<uint8>& input) { - return CreateFromPrivateKeyInfoWithParams(slot, - input, - true /* permanent */, - true /* sensitive */); -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( - const std::vector<uint8>& input) { - scoped_ptr<RSAPrivateKey> result(InitPublicPart(input)); - if (!result) - return NULL; - - ScopedSECItem ck_id( - PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); - if (!ck_id.get()) { - NOTREACHED(); - return NULL; - } - - // Search all slots in all modules for the key with the given ID. - AutoSECMODListReadLock auto_lock; - SECMODModuleList* head = SECMOD_GetDefaultModuleList(); - for (SECMODModuleList* item = head; item != NULL; item = item->next) { - int slot_count = item->module->loaded ? item->module->slotCount : 0; - for (int i = 0; i < slot_count; i++) { - // Finally...Look for the key! - result->key_ = PK11_FindKeyByKeyID(item->module->slots[i], - ck_id.get(), NULL); - if (result->key_) - return result.release(); - } - } - - // We didn't find the key. - return NULL; -} - -// static -RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfoInSlot( - const std::vector<uint8>& input, - PK11SlotInfo* slot) { - if (!slot) - return NULL; - - scoped_ptr<RSAPrivateKey> result(InitPublicPart(input)); - if (!result) - return NULL; - - ScopedSECItem ck_id( - PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); - if (!ck_id.get()) { - NOTREACHED(); - return NULL; - } - - result->key_ = PK11_FindKeyByKeyID(slot, ck_id.get(), NULL); - if (!result->key_) - return NULL; - return result.release(); -} -#endif - RSAPrivateKey* RSAPrivateKey::Copy() const { RSAPrivateKey* copy = new RSAPrivateKey(); copy->key_ = SECKEY_CopyPrivateKey(key_); @@ -241,92 +148,4 @@ RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { EnsureNSSInit(); } -// static -RSAPrivateKey* RSAPrivateKey::CreateWithParams(PK11SlotInfo* slot, - uint16 num_bits, - bool permanent, - bool sensitive) { - if (!slot) - return NULL; - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - PK11RSAGenParams param; - param.keySizeInBits = num_bits; - param.pe = 65537L; - result->key_ = PK11_GenerateKeyPair(slot, - CKM_RSA_PKCS_KEY_PAIR_GEN, - ¶m, - &result->public_key_, - permanent, - sensitive, - NULL); - if (!result->key_) - return NULL; - - return result.release(); -} - -// static -RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( - PK11SlotInfo* slot, - const std::vector<uint8>& input, - bool permanent, - bool sensitive) { - if (!slot) - return NULL; - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); - - ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); - if (!arena) { - NOTREACHED(); - return NULL; - } - - // Excess data is illegal, but NSS silently accepts it, so first ensure that - // |input| consists of a single ASN.1 element. - SECItem input_item; - input_item.data = const_cast<unsigned char*>(&input.front()); - input_item.len = input.size(); - SECItem der_private_key_info; - SECStatus rv = SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, - SEC_ASN1_GET(SEC_AnyTemplate), - &input_item); - if (rv != SECSuccess) - return NULL; - - // Allow the private key to be used for key unwrapping, data decryption, - // and signature generation. - const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | - KU_DIGITAL_SIGNATURE; - rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot, &der_private_key_info, NULL, NULL, permanent, sensitive, - key_usage, &result->key_, NULL); - if (rv != SECSuccess) - return NULL; - - result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); - if (!result->public_key_) - return NULL; - - return result.release(); -} - -#if defined(USE_NSS_CERTS) -// static -RSAPrivateKey* RSAPrivateKey::InitPublicPart(const std::vector<uint8>& input) { - EnsureNSSInit(); - - scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey()); - result->public_key_ = GetRSAPublicKey(input).release(); - if (!result->public_key_) { - NOTREACHED(); - return NULL; - } - - return result.release(); -} -#endif // defined(USE_NSS_CERTS) - } // namespace crypto diff --git a/crypto/rsa_private_key_nss_unittest.cc b/crypto/rsa_private_key_nss_unittest.cc deleted file mode 100644 index dad6688..0000000 --- a/crypto/rsa_private_key_nss_unittest.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "crypto/rsa_private_key.h" - -#include <keyhi.h> -#include <pk11pub.h> - -#include "base/memory/scoped_ptr.h" -#include "crypto/scoped_test_nss_db.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace crypto { - -// TODO(davidben): These tests assume NSS is used for both the internal crypto -// library and the platform key store. See https://crbug.com/478777. -#if defined(USE_NSS_CERTS) - -class RSAPrivateKeyNSSTest : public testing::Test { - public: - RSAPrivateKeyNSSTest() {} - ~RSAPrivateKeyNSSTest() override {} - - private: - ScopedTestNSSDB test_nssdb_; - - DISALLOW_COPY_AND_ASSIGN(RSAPrivateKeyNSSTest); -}; - -TEST_F(RSAPrivateKeyNSSTest, FindFromPublicKey) { - // Create a keypair, which will put the keys in the user's NSSDB. - scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256)); - - std::vector<uint8> public_key; - ASSERT_TRUE(key_pair->ExportPublicKey(&public_key)); - - scoped_ptr<crypto::RSAPrivateKey> key_pair_2( - crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); - - EXPECT_EQ(key_pair->key_->pkcs11ID, key_pair_2->key_->pkcs11ID); -} - -TEST_F(RSAPrivateKeyNSSTest, FailedFindFromPublicKey) { - // Create a keypair, which will put the keys in the user's NSSDB. - scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256)); - - std::vector<uint8> public_key; - ASSERT_TRUE(key_pair->ExportPublicKey(&public_key)); - - // Remove the keys from the DB, and make sure we can't find them again. - if (key_pair->key_) { - PK11_DestroyTokenObject(key_pair->key_->pkcs11Slot, - key_pair->key_->pkcs11ID); - } - if (key_pair->public_key_) { - PK11_DestroyTokenObject(key_pair->public_key_->pkcs11Slot, - key_pair->public_key_->pkcs11ID); - } - - EXPECT_EQ(NULL, crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); -} - -#endif // USE_NSS_CERTS - -} // namespace crypto diff --git a/net/net.gyp b/net/net.gyp index 9c35d10..3db83b5 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -506,6 +506,7 @@ # TODO(mmenke): This depends on icu, figure out a way to build tests # without icu. '../base/base.gyp:test_support_base', + '../crypto/crypto.gyp:crypto', '../testing/gtest.gyp:gtest', '../testing/gmock.gyp:gmock', ], diff --git a/net/test/cert_test_util.h b/net/test/cert_test_util.h index 8ad5664..219ccd8 100644 --- a/net/test/cert_test_util.h +++ b/net/test/cert_test_util.h @@ -12,8 +12,6 @@ #include "net/cert/x509_certificate.h" #if defined(USE_NSS_CERTS) -#include "base/memory/scoped_ptr.h" - // From <pk11pub.h> typedef struct PK11SlotInfoStr PK11SlotInfo; #endif @@ -31,13 +29,12 @@ namespace net { class EVRootCAMetadata; #if defined(USE_NSS_CERTS) -// Imports a private key from file |key_filename| in |dir|. The file must -// contain a PKCS#8 PrivateKeyInfo in DER encoding. The key is imported to -// |slot|. -scoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile( - const base::FilePath& dir, - const std::string& key_filename, - PK11SlotInfo* slot); +// Imports a private key from file |key_filename| in |dir| into |slot|. The file +// must contain a PKCS#8 PrivateKeyInfo in DER encoding. Returns true on success +// and false on failure. +bool ImportSensitiveKeyFromFile(const base::FilePath& dir, + const std::string& key_filename, + PK11SlotInfo* slot); bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert, PK11SlotInfo* slot); diff --git a/net/test/cert_test_util_nss.cc b/net/test/cert_test_util_nss.cc index 74884c7..4427ceb 100644 --- a/net/test/cert_test_util_nss.cc +++ b/net/test/cert_test_util_nss.cc @@ -9,30 +9,22 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "crypto/nss_key_util.h" #include "crypto/nss_util.h" -#include "crypto/rsa_private_key.h" +#include "crypto/scoped_nss_types.h" #include "net/cert/cert_type.h" namespace net { -scoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile( - const base::FilePath& dir, - const std::string& key_filename, - PK11SlotInfo* slot) { -#if defined(USE_OPENSSL) - // TODO(davidben): Port RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo away - // from RSAPrivateKey so it doesn't make assumptions about the internal crypto - // library. Instead, return a ScopedSECKEYPrivateKey or have this function - // just return bool. https://crbug.com/478777 - NOTIMPLEMENTED(); - return nullptr; -#else +bool ImportSensitiveKeyFromFile(const base::FilePath& dir, + const std::string& key_filename, + PK11SlotInfo* slot) { base::FilePath key_path = dir.AppendASCII(key_filename); std::string key_pkcs8; bool success = base::ReadFileToString(key_path, &key_pkcs8); if (!success) { LOG(ERROR) << "Failed to read file " << key_path.value(); - return scoped_ptr<crypto::RSAPrivateKey>(); + return false; } const uint8* key_pkcs8_begin = @@ -40,13 +32,12 @@ scoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile( std::vector<uint8> key_vector(key_pkcs8_begin, key_pkcs8_begin + key_pkcs8.length()); - scoped_ptr<crypto::RSAPrivateKey> private_key( - crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot, - key_vector)); + crypto::ScopedSECKEYPrivateKey private_key( + crypto::ImportNSSKeyFromPrivateKeyInfo(slot, key_vector, + true /* permanent */)); LOG_IF(ERROR, !private_key) << "Could not create key from file " << key_path.value(); - return private_key.Pass(); -#endif + return private_key; } bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert, |