diff options
author | davidben <davidben@chromium.org> | 2015-05-01 08:35:56 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-01 15:36:27 +0000 |
commit | a46a990b2ccae2b66e87b5f76d2866044dc3182e (patch) | |
tree | f0102746c81371d47dc304c401dc414ee5a570a9 | |
parent | b847f7bb3b352907f617db6896bca0d3489ccfb4 (diff) | |
download | chromium_src-a46a990b2ccae2b66e87b5f76d2866044dc3182e.zip chromium_src-a46a990b2ccae2b66e87b5f76d2866044dc3182e.tar.gz chromium_src-a46a990b2ccae2b66e87b5f76d2866044dc3182e.tar.bz2 |
Don't use RSAPrivateKey in NSS integration code.
Currently some NSS platform integration logic transits private keys through
RSAPrivateKey on CrOS. This prevents incrementally switching RSAPrivateKey to
BoringSSL while keeping platform integrations on NSS.
The intent of this change is to clarify RSAPrivateKey as a BoringSSL vs NSS
internal crypto library (use_openssl=0 vs use_openssl=1) abstraction. It's
primarily to be used with SignatureCreator. Code which uses NSS based on
use_nss_certs rather than use_openssl because the underlying platform is NSS
should call NSS routines directly, or introduce different abstractions.
Remove the problematic RSAPrivateKey methods and instead add
crypto/nss_key_util.h which contains some helper functions for manipulating NSS
keys. This is sufficient to allow consumers of the removed methods to use NSS
directly with about as much code. (This should not set back migrating that
logic to NSS as that code was already very NSS-specific; those APIs assumed
PK11SlotInfo.)
nss_key_util.h, like nss_util.h, is built whenever NSS is used either
internally or for platform integrations. This is so rsa_private_key_nss.cc can
continue to use the helper functions to implement the NSS-agnostic interface.
With this, the chimera CrOS configuration should build. The RSAPrivateKey logic
is functional with the exception of some logic in components/ownership. That
will be resolved in a future CL.
BUG=478777
Review URL: https://codereview.chromium.org/1106103003
Cr-Commit-Position: refs/heads/master@{#327909}
-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 | 38 | ||||
-rw-r--r-- | chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc | 11 | ||||
-rw-r--r-- | chrome/browser/chromeos/platform_keys/platform_keys_nss.cc | 36 | ||||
-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 | 18 | ||||
-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 | 161 | ||||
-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 |
19 files changed, 452 insertions, 430 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..06c5897 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,10 @@ 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>(); + crypto::ScopedSECKEYPrivateKey rsa_key( + crypto::FindNSSKeyFromPublicKeyInfoInSlot(public_key_vector, slot)); + if (!rsa_key || SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey) + return nullptr; return rsa_key.Pass(); } @@ -81,7 +82,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 +94,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 +123,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 +144,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..4a36a9d 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" @@ -124,10 +126,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/platform_keys/platform_keys_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc index af14d11..63131a3 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,28 @@ 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) { + 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 +446,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 +468,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 +477,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 +503,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..cab5ffa 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,18 @@ bool OwnerKeyUtilImpl::ImportPublicKey(std::vector<uint8>* output) { crypto::RSAPrivateKey* OwnerKeyUtilImpl::FindPrivateKeyInSlot( const std::vector<uint8>& key, PK11SlotInfo* slot) { - return crypto::RSAPrivateKey::FindFromPublicKeyInfoInSlot(key, slot); + 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..260d3b6 --- /dev/null +++ b/crypto/nss_key_util.cc @@ -0,0 +1,161 @@ +// 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) { + 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 ca90dbb..2dcc2c8 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, |