summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspang <spang@chromium.org>2015-05-01 14:01:57 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-01 21:02:38 +0000
commit9ce3458d9a03b38ca717291d08d564e12fd8254a (patch)
treeb0f4570294cfb11e72f16cf0e424f40313ff2fdb
parentc10dfc7c662c078a7310e6c7d6041763150ce494 (diff)
downloadchromium_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.cc9
-rw-r--r--chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc38
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc11
-rw-r--r--chrome/browser/chromeos/platform_keys/platform_keys_nss.cc36
-rw-r--r--components/ownership.gypi5
-rw-r--r--components/ownership/BUILD.gn5
-rw-r--r--components/ownership/owner_key_util_impl.cc18
-rw-r--r--crypto/BUILD.gn23
-rw-r--r--crypto/crypto.gyp16
-rw-r--r--crypto/crypto.gypi2
-rw-r--r--crypto/nss_key_util.cc161
-rw-r--r--crypto/nss_key_util.h58
-rw-r--r--crypto/nss_key_util_unittest.cc87
-rw-r--r--crypto/rsa_private_key.h69
-rw-r--r--crypto/rsa_private_key_nss.cc233
-rw-r--r--crypto/rsa_private_key_nss_unittest.cc66
-rw-r--r--net/net.gyp1
-rw-r--r--net/test/cert_test_util.h15
-rw-r--r--net/test/cert_test_util_nss.cc29
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,
- &param, &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,
+ &param,
+ &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,