diff options
author | spang <spang@chromium.org> | 2015-05-01 14:01:57 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-01 21:02:38 +0000 |
commit | 9ce3458d9a03b38ca717291d08d564e12fd8254a (patch) | |
tree | b0f4570294cfb11e72f16cf0e424f40313ff2fdb | |
parent | c10dfc7c662c078a7310e6c7d6041763150ce494 (diff) | |
download | chromium_src-9ce3458d9a03b38ca717291d08d564e12fd8254a.zip chromium_src-9ce3458d9a03b38ca717291d08d564e12fd8254a.tar.gz chromium_src-9ce3458d9a03b38ca717291d08d564e12fd8254a.tar.bz2 |
Revert of Don't use RSAPrivateKey in NSS integration code. (patchset #6 id:100001 of https://codereview.chromium.org/1106103003/)
Reason for revert:
Causes SEGV during login on Chrome OS
BUG=483606
Original issue's description:
> 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
>
> Committed: https://crrev.com/a46a990b2ccae2b66e87b5f76d2866044dc3182e
> Cr-Commit-Position: refs/heads/master@{#327909}
TBR=rsleevi@chromium.org,pneubeck@chromium.org,dpolukhin@chromium.org,caitkp@chromium.org,davidben@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=483606
Review URL: https://codereview.chromium.org/1118263003
Cr-Commit-Position: refs/heads/master@{#327978}
-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, 430 insertions, 452 deletions
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc index c96e922..2607ace 100644 --- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc @@ -45,7 +45,6 @@ #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" @@ -119,11 +118,11 @@ std::vector<uint8> GetOwnerPublicKey() { kOwnerPublicKey + arraysize(kOwnerPublicKey)); } -bool CreateOwnerKeyInSlot(PK11SlotInfo* slot) { +scoped_ptr<crypto::RSAPrivateKey> CreateOwnerKeyInSlot(PK11SlotInfo* slot) { const std::vector<uint8> key(kOwnerPrivateKey, kOwnerPrivateKey + arraysize(kOwnerPrivateKey)); - return crypto::ImportNSSKeyFromPrivateKeyInfo(slot, key, - true /* permanent */); + return make_scoped_ptr( + crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot, key)); } } // namespace @@ -473,7 +472,7 @@ TEST_F(CryptohomeAuthenticatorTest, ResolveOwnerNeededSuccess) { crypto::ScopedPK11Slot user_slot( crypto::GetPublicSlotForChromeOSUser(user_context_.GetUserIDHash())); - ASSERT_TRUE(CreateOwnerKeyInSlot(user_slot.get())); + 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 06c5897..3321ed9 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,7 +5,6 @@ #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" @@ -23,8 +22,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 { @@ -58,7 +57,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. -crypto::ScopedSECKEYPrivateKey GetPrivateKeyOnWorkerThread( +scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( PK11SlotInfo* slot, const std::string& public_key) { const uint8* public_key_uint8 = @@ -66,10 +65,10 @@ crypto::ScopedSECKEYPrivateKey GetPrivateKeyOnWorkerThread( std::vector<uint8> public_key_vector( public_key_uint8, public_key_uint8 + public_key.size()); - crypto::ScopedSECKEYPrivateKey rsa_key( - crypto::FindNSSKeyFromPublicKeyInfoInSlot(public_key_vector, slot)); - if (!rsa_key || SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey) - return nullptr; + 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>(); return rsa_key.Pass(); } @@ -82,7 +81,7 @@ void SignDataOnWorkerThread( const std::string& data, const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, const base::Callback<void(const std::string&)>& callback) { - crypto::ScopedSECKEYPrivateKey private_key( + scoped_ptr<crypto::RSAPrivateKey> private_key( GetPrivateKeyOnWorkerThread(slot.get(), public_key)); if (!private_key) { LOG(ERROR) << "Private key for signing data not found"; @@ -94,7 +93,8 @@ 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.get(), + data.size(), + private_key->key(), SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION) != SECSuccess) { LOG(ERROR) << "Failed to sign data"; response_task_runner->PostTask(FROM_HERE, @@ -123,20 +123,17 @@ void CreateTpmKeyPairOnWorkerThread( return; } - crypto::ScopedSECKEYPublicKey public_key_obj; - crypto::ScopedSECKEYPrivateKey private_key_obj; - if (!crypto::GenerateRSAKeyPairNSS(slot.get(), kKeyModulusLength, - true /* permanent */, &public_key_obj, - &private_key_obj)) { + scoped_ptr<crypto::RSAPrivateKey> rsa_key( + crypto::RSAPrivateKey::CreateSensitive(slot.get(), kKeyModulusLength)); + if (!rsa_key) { LOG(ERROR) << "Failed to create an RSA key."; response_task_runner->PostTask(FROM_HERE, base::Bind(callback, std::string())); return; } - crypto::ScopedSECItem public_key_der( - SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_obj.get())); - if (!public_key_der) { + std::vector<uint8> created_public_key; + if (!rsa_key->ExportPublicKey(&created_public_key)) { LOG(ERROR) << "Failed to export public key."; response_task_runner->PostTask(FROM_HERE, base::Bind(callback, std::string())); @@ -144,9 +141,10 @@ void CreateTpmKeyPairOnWorkerThread( } response_task_runner->PostTask( - FROM_HERE, base::Bind(callback, std::string(reinterpret_cast<const char*>( - public_key_der->data), - public_key_der->len))); + FROM_HERE, + base::Bind(callback, + std::string(created_public_key.begin(), + created_public_key.end()))); } } // namespace diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc index 4a36a9d..a96f0aa 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc @@ -4,8 +4,6 @@ #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" -#include <keyhi.h> - #include <algorithm> #include <string> @@ -31,9 +29,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" @@ -126,9 +124,10 @@ bool DoesPrivateKeyExistAsyncHelper( std::vector<uint8> public_key; if (!owner_key_util->ImportPublicKey(&public_key)) return false; - crypto::ScopedSECKEYPrivateKey key = - crypto::FindNSSKeyFromPublicKeyInfo(public_key); - return key && SECKEY_GetPrivateKeyType(key.get()) == rsaKey; + scoped_ptr<crypto::RSAPrivateKey> key( + crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key)); + bool is_owner = key.get() != NULL; + return is_owner; } // 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 63131a3..af14d11 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc +++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc @@ -31,8 +31,7 @@ #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/nss_key_util.h" -#include "crypto/scoped_nss_types.h" +#include "crypto/rsa_private_key.h" #include "net/base/crypto_module.h" #include "net/base/net_errors.h" #include "net/cert/cert_database.h" @@ -401,28 +400,25 @@ GetTokensState::GetTokensState(const GetTokensCallback& callback) // Does the actual key generation on a worker thread. Used by // GenerateRSAKeyWithDB(). void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { - crypto::ScopedSECKEYPublicKey public_key; - crypto::ScopedSECKEYPrivateKey private_key; - if (!crypto::GenerateRSAKeyPairNSS( - state->slot_.get(), state->modulus_length_bits_, true /* permanent */, - &public_key, &private_key)) { + scoped_ptr<crypto::RSAPrivateKey> rsa_key( + crypto::RSAPrivateKey::CreateSensitive(state->slot_.get(), + state->modulus_length_bits_)); + if (!rsa_key) { LOG(ERROR) << "Couldn't create key."; state->OnError(FROM_HERE, kErrorInternal); return; } - crypto::ScopedSECItem public_key_der( - SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get())); - if (!public_key_der) { - // TODO(pneubeck): Remove private_key and public_key from storage. + std::vector<uint8> public_key_spki_der; + if (!rsa_key->ExportPublicKey(&public_key_spki_der)) { + // TODO(pneubeck): Remove rsa_key from storage. LOG(ERROR) << "Couldn't export public key."; state->OnError(FROM_HERE, kErrorInternal); return; } state->CallBack( FROM_HERE, - std::string(reinterpret_cast<const char*>(public_key_der->data), - public_key_der->len), + std::string(public_key_spki_der.begin(), public_key_spki_der.end()), std::string() /* no error */); } @@ -446,13 +442,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_|. - crypto::ScopedSECKEYPrivateKey rsa_key( - crypto::FindNSSKeyFromPublicKeyInfo(public_key_vector)); + scoped_ptr<crypto::RSAPrivateKey> rsa_key( + crypto::RSAPrivateKey::FindFromPublicKeyInfo(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 || SECKEY_GetPrivateKeyType(rsa_key.get()) != rsaKey || - (state->slot_ && rsa_key->pkcs11Slot != state->slot_)) { + if (!rsa_key || + (state->slot_ && rsa_key->key()->pkcs11Slot != state->slot_)) { state->OnError(FROM_HERE, kErrorKeyNotFound); return; } @@ -468,7 +464,7 @@ void SignRSAOnWorkerThread(scoped_ptr<SignRSAState> state) { state->data_.size()}; // Compute signature of hash. - int signature_len = PK11_SignatureLen(rsa_key.get()); + int signature_len = PK11_SignatureLen(rsa_key->key()); if (signature_len <= 0) { state->OnError(FROM_HERE, kErrorInternal); return; @@ -477,7 +473,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.get(), &signature_output, &input) == SECSuccess) + if (PK11_Sign(rsa_key->key(), &signature_output, &input) == SECSuccess) signature_str.assign(signature.begin(), signature.end()); } else { SECOidTag sign_alg_tag = SEC_OID_UNKNOWN; @@ -503,7 +499,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.get(), sign_alg_tag) == SECSuccess) { + state->data_.size(), rsa_key->key(), 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 4784259..0b95fe2 100644 --- a/components/ownership.gypi +++ b/components/ownership.gypi @@ -35,11 +35,6 @@ '<(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 cdaf227..1bca927 100644 --- a/components/ownership/BUILD.gn +++ b/components/ownership/BUILD.gn @@ -2,7 +2,6 @@ # 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") { @@ -30,10 +29,6 @@ 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 cab5ffa..bc7208e 100644 --- a/components/ownership/owner_key_util_impl.cc +++ b/components/ownership/owner_key_util_impl.cc @@ -8,12 +8,7 @@ #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 { @@ -59,18 +54,7 @@ bool OwnerKeyUtilImpl::ImportPublicKey(std::vector<uint8>* output) { crypto::RSAPrivateKey* OwnerKeyUtilImpl::FindPrivateKeyInSlot( const std::vector<uint8>& key, PK11SlotInfo* 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 + return crypto::RSAPrivateKey::FindFromPublicKeyInfoInSlot(key, slot); } #endif // defined(USE_NSS_CERTS) diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn index f84c4d4..c1eabe6 100644 --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn @@ -50,8 +50,6 @@ 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", @@ -173,12 +171,10 @@ component("crypto") { ] } - # Some files are built when NSS is used at all, either for the internal crypto - # library or the platform certificate library. + # Remove nss_util when NSS is used for neither the internal crypto library + # nor 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", @@ -230,12 +226,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", @@ -244,16 +240,15 @@ test("crypto_unittests") { "symmetric_key_unittest.cc", ] - # Some files are built when NSS is used at all, either for the internal crypto - # library or the platform certificate library. + # Remove nss_util when NSS is used for neither the internal crypto library + # nor the platform certificate library. if (use_openssl && !use_nss_certs) { - sources -= [ - "nss_key_util_unittest.cc", - "nss_util_unittest.cc", - ] + sources -= [ "nss_util_unittest.cc" ] } - if (!use_openssl) { + if (use_openssl) { + sources -= [ "rsa_private_key_nss_unittest.cc" ] + } else { sources -= [ "openssl_bio_string_unittest.cc" ] } diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index e6bff0b..00b59b5 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -143,11 +143,9 @@ ], },], [ 'use_openssl==1 and use_nss_certs==0', { - # Some files are built when NSS is used at all, either for the - # internal crypto library or the platform certificate library. + # NSS is used for neither the internal crypto library nor the + # platform certificate library. 'sources!': [ - 'nss_key_util.cc', - 'nss_key_util.h', 'nss_util.cc', 'nss_util.h', 'nss_util_internal.h', @@ -170,13 +168,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', @@ -207,10 +205,9 @@ ], }], [ 'use_openssl == 1 and use_nss_certs == 0', { - # Some files are built when NSS is used at all, either for the - # internal crypto library or the platform certificate library. + # nss_util is built if NSS is used for either the internal crypto + # library or the platform certificate library. 'sources!': [ - 'nss_key_util_unittest.cc', 'nss_util_unittest.cc', ], }], @@ -227,6 +224,9 @@ '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 73b3332..4456b10 100644 --- a/crypto/crypto.gypi +++ b/crypto/crypto.gypi @@ -67,8 +67,6 @@ '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 deleted file mode 100644 index 260d3b6..0000000 --- a/crypto/nss_key_util.cc +++ /dev/null @@ -1,161 +0,0 @@ -// 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 deleted file mode 100644 index 12b948d..0000000 --- a/crypto/nss_key_util.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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 deleted file mode 100644 index f8de8e2..0000000 --- a/crypto/nss_key_util_unittest.cc +++ /dev/null @@ -1,87 +0,0 @@ -// 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 637be38..9ab9c57 100644 --- a/crypto/rsa_private_key.h +++ b/crypto/rsa_private_key.h @@ -191,6 +191,44 @@ 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 @@ -213,9 +251,38 @@ class CRYPTO_EXPORT RSAPrivateKey { FRIEND_TEST_ALL_PREFIXES(RSAPrivateKeyNSSTest, FailedFindFromPublicKey); #endif - // Constructor is private. Use one of the Create*() methods above instead. + // Constructor is private. Use one of the Create*() or Find*() + // 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 88e55fa..c9e6a87 100644 --- a/crypto/rsa_private_key_nss.cc +++ b/crypto/rsa_private_key_nss.cc @@ -7,6 +7,7 @@ #include <cryptohi.h> #include <keyhi.h> #include <pk11pub.h> +#include <secmod.h> #include <list> @@ -14,8 +15,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. @@ -37,6 +38,37 @@ 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 { @@ -53,22 +85,10 @@ RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { EnsureNSSInit(); ScopedPK11Slot slot(PK11_GetInternalSlot()); - 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; + return CreateWithParams(slot.get(), + num_bits, + false /* not permanent */, + false /* not sensitive */); } // static @@ -77,15 +97,11 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( EnsureNSSInit(); ScopedPK11Slot slot(PK11_GetInternalSlot()); - 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()); + return CreateFromPrivateKeyInfoWithParams( + slot.get(), + input, + false /* not permanent */, + false /* not sensitive */); } // static @@ -104,6 +120,83 @@ 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_); @@ -148,4 +241,92 @@ 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 new file mode 100644 index 0000000..dad6688 --- /dev/null +++ b/crypto/rsa_private_key_nss_unittest.cc @@ -0,0 +1,66 @@ +// 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 2dcc2c8..ca90dbb 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -506,7 +506,6 @@ # 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 219ccd8..8ad5664 100644 --- a/net/test/cert_test_util.h +++ b/net/test/cert_test_util.h @@ -12,6 +12,8 @@ #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 @@ -29,12 +31,13 @@ namespace net { class EVRootCAMetadata; #if defined(USE_NSS_CERTS) -// 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); +// 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); 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 4427ceb..74884c7 100644 --- a/net/test/cert_test_util_nss.cc +++ b/net/test/cert_test_util_nss.cc @@ -9,22 +9,30 @@ #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/scoped_nss_types.h" +#include "crypto/rsa_private_key.h" #include "net/cert/cert_type.h" namespace net { -bool ImportSensitiveKeyFromFile(const base::FilePath& dir, - const std::string& key_filename, - PK11SlotInfo* slot) { +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 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 false; + return scoped_ptr<crypto::RSAPrivateKey>(); } const uint8* key_pkcs8_begin = @@ -32,12 +40,13 @@ bool ImportSensitiveKeyFromFile(const base::FilePath& dir, std::vector<uint8> key_vector(key_pkcs8_begin, key_pkcs8_begin + key_pkcs8.length()); - crypto::ScopedSECKEYPrivateKey private_key( - crypto::ImportNSSKeyFromPrivateKeyInfo(slot, key_vector, - true /* permanent */)); + scoped_ptr<crypto::RSAPrivateKey> private_key( + crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot, + key_vector)); LOG_IF(ERROR, !private_key) << "Could not create key from file " << key_path.value(); - return private_key; + return private_key.Pass(); +#endif } bool ImportClientCertToSlot(const scoped_refptr<X509Certificate>& cert, |