Commit 83e1ae34 authored by pneubeck@chromium.org's avatar pneubeck@chromium.org

Remove NSSCertDatabase from ClientCertStoreChromeOS unittest.

The database was only used to import a PKCS#12 file. By changing to separate key (PKCS#8 format) and cert (X509 in PEM encoding), only dependencies on the lower level RSAPrivateKey, X509Certificate and PK11_* NSS functions are required.
Note this removes at the same time a call to the deprecated NSSCertDatabase::GetInstance().

Also
- fixes multi profile cases of the unit test and the CA matching (the latter is now identical to all other platforms).
- fixes a bug in the matching of client certs from software slots, because of reused cert database names
- gets rid of the error output that occurred during the PKCS12 import because the file contained also a CA cert:
  [ERROR:nsPKCS12Blob.cpp(219)] Could not grab a handle to the certificate in the slot from the corresponding PKCS#12 DER certificate.

BUG=210525, 329735,315285

Review URL: https://codereview.chromium.org/394013005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284056 0039d316-1c4b-4281-b951-d872f2087c98
parent fdc67c49
...@@ -57,7 +57,7 @@ namespace crypto { ...@@ -57,7 +57,7 @@ namespace crypto {
namespace { namespace {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
const char kNSSDatabaseName[] = "Real NSS database"; const char kUserNSSDatabaseName[] = "UserNSSDB";
// Constants for loading the Chrome OS TPM-backed PKCS #11 library. // Constants for loading the Chrome OS TPM-backed PKCS #11 library.
const char kChapsModuleName[] = "Chaps"; const char kChapsModuleName[] = "Chaps";
...@@ -287,7 +287,8 @@ class NSSInitSingleton { ...@@ -287,7 +287,8 @@ class NSSInitSingleton {
PK11SlotInfo* tpm_slot; PK11SlotInfo* tpm_slot;
}; };
PK11SlotInfo* OpenPersistentNSSDBForPath(const base::FilePath& path) { PK11SlotInfo* OpenPersistentNSSDBForPath(const std::string& db_name,
const base::FilePath& path) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
// NSS is allowed to do IO on the current thread since dispatching // NSS is allowed to do IO on the current thread since dispatching
// to a dedicated thread would still have the affect of blocking // to a dedicated thread would still have the affect of blocking
...@@ -299,7 +300,7 @@ class NSSInitSingleton { ...@@ -299,7 +300,7 @@ class NSSInitSingleton {
LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory."; LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
return NULL; return NULL;
} }
return OpenUserDB(nssdb_path, kNSSDatabaseName); return OpenUserDB(nssdb_path, db_name);
} }
void EnableTPMTokenForNSS() { void EnableTPMTokenForNSS() {
...@@ -469,7 +470,9 @@ class NSSInitSingleton { ...@@ -469,7 +470,9 @@ class NSSInitSingleton {
return false; return false;
DVLOG(2) << "Opening NSS DB " << path.value(); DVLOG(2) << "Opening NSS DB " << path.value();
ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(path)); std::string db_name = base::StringPrintf(
"%s %s", kUserNSSDatabaseName, username_hash.c_str());
ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path));
chromeos_user_map_[username_hash] = chromeos_user_map_[username_hash] =
new ChromeOSUserData(public_slot.Pass()); new ChromeOSUserData(public_slot.Pass());
return true; return true;
...@@ -861,10 +864,11 @@ class NSSInitSingleton { ...@@ -861,10 +864,11 @@ class NSSInitSingleton {
#endif #endif
static PK11SlotInfo* OpenUserDB(const base::FilePath& path, static PK11SlotInfo* OpenUserDB(const base::FilePath& path,
const char* description) { const std::string& description) {
const std::string modspec = const std::string modspec =
base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
path.value().c_str(), description); path.value().c_str(),
description.c_str());
PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
if (db_slot) { if (db_slot) {
if (PK11_NeedUserInit(db_slot)) if (PK11_NeedUserInit(db_slot))
......
...@@ -639,6 +639,7 @@ source_set("test_support") { ...@@ -639,6 +639,7 @@ source_set("test_support") {
"socket/socket_test_util.h", "socket/socket_test_util.h",
"test/cert_test_util.cc", "test/cert_test_util.cc",
"test/cert_test_util.h", "test/cert_test_util.h",
"test/cert_test_util_nss.cc",
"test/ct_test_util.cc", "test/ct_test_util.cc",
"test/ct_test_util.h", "test/ct_test_util.h",
"test/embedded_test_server/embedded_test_server.cc", "test/embedded_test_server/embedded_test_server.cc",
...@@ -707,6 +708,12 @@ source_set("test_support") { ...@@ -707,6 +708,12 @@ source_set("test_support") {
] ]
} }
if (!use_nss_certs) {
sources -= [
"test/cert_test_util_nss.cc",
]
}
forward_dependent_configs_from = deps forward_dependent_configs_from = deps
} }
......
...@@ -938,6 +938,7 @@ ...@@ -938,6 +938,7 @@
'socket/socket_test_util.h', 'socket/socket_test_util.h',
'test/cert_test_util.cc', 'test/cert_test_util.cc',
'test/cert_test_util.h', 'test/cert_test_util.h',
'test/cert_test_util_nss.cc',
'test/ct_test_util.cc', 'test/ct_test_util.cc',
'test/ct_test_util.h', 'test/ct_test_util.h',
'test/embedded_test_server/embedded_test_server.cc', 'test/embedded_test_server/embedded_test_server.cc',
...@@ -1021,6 +1022,11 @@ ...@@ -1021,6 +1022,11 @@
'dns/mock_mdns_socket_factory.h' 'dns/mock_mdns_socket_factory.h'
] ]
}], }],
[ 'use_nss != 1', {
'sources!': [
'test/cert_test_util_nss.cc',
],
}],
], ],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations. # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [4267, ], 'msvs_disabled_warnings': [4267, ],
......
...@@ -67,28 +67,4 @@ void ClientCertStoreChromeOS::DidGetPrivateSlot( ...@@ -67,28 +67,4 @@ void ClientCertStoreChromeOS::DidGetPrivateSlot(
ClientCertStoreNSS::GetClientCerts(*request, selected_certs, callback); ClientCertStoreNSS::GetClientCerts(*request, selected_certs, callback);
} }
void ClientCertStoreChromeOS::InitForTesting(
crypto::ScopedPK11Slot public_slot,
crypto::ScopedPK11Slot private_slot) {
profile_filter_.Init(public_slot.Pass(), private_slot.Pass());
}
bool ClientCertStoreChromeOS::SelectClientCertsForTesting(
const CertificateList& input_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
CERTCertList* cert_list = CERT_NewCertList();
if (!cert_list)
return false;
for (size_t i = 0; i < input_certs.size(); ++i) {
CERT_AddCertToListTail(
cert_list, CERT_DupCertificate(input_certs[i]->os_cert_handle()));
}
GetClientCertsImpl(cert_list, request, false, selected_certs);
CERT_DestroyCertList(cert_list);
return true;
}
} // namespace net } // namespace net
...@@ -40,21 +40,6 @@ class NET_EXPORT ClientCertStoreChromeOS : public ClientCertStoreNSS { ...@@ -40,21 +40,6 @@ class NET_EXPORT ClientCertStoreChromeOS : public ClientCertStoreNSS {
const base::Closure& callback, const base::Closure& callback,
crypto::ScopedPK11Slot private_slot); crypto::ScopedPK11Slot private_slot);
// Allows tests to initialize the cert store with the given slots.
// Must be called before SelectClientCertsForTesting.
void InitForTesting(crypto::ScopedPK11Slot public_slot,
crypto::ScopedPK11Slot private_slot);
// A hook for testing. Filters |input_certs| using the logic being used to
// filter the system store when GetClientCerts() is called.
// Implemented by creating a list of certificates that otherwise would be
// extracted from the system store and filtering it using the common logic
// (less adequate than the approach used on Windows).
bool SelectClientCertsForTesting(const CertificateList& input_certs,
const SSLCertRequestInfo& cert_request_info,
CertificateList* selected_certs);
std::string username_hash_; std::string username_hash_;
NSSProfileFilterChromeOS profile_filter_; NSSProfileFilterChromeOS profile_filter_;
......
...@@ -11,16 +11,37 @@ ...@@ -11,16 +11,37 @@
#include "net/cert/x509_cert_types.h" #include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h" #include "net/cert/x509_certificate.h"
#if defined(USE_NSS)
#include "base/memory/scoped_ptr.h"
// From <pk11pub.h>
typedef struct PK11SlotInfoStr PK11SlotInfo;
#endif
namespace base { namespace base {
class FilePath; class FilePath;
} }
namespace crypto {
class RSAPrivateKey;
}
namespace net { namespace net {
class EVRootCAMetadata; class EVRootCAMetadata;
// Imports all of the certificates in |cert_file|, a file in |certs_dir|, #if defined(USE_NSS)
// // into a CertificateList. // 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);
#endif
// Imports all of the certificates in |cert_file|, a file in |certs_dir|, into a
// CertificateList.
CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir, CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir,
const std::string& cert_file, const std::string& cert_file,
int format); int format);
......
// Copyright 2014 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 "net/test/cert_test_util.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "crypto/rsa_private_key.h"
namespace net {
scoped_ptr<crypto::RSAPrivateKey> ImportSensitiveKeyFromFile(
const base::FilePath& dir,
const std::string& key_filename,
PK11SlotInfo* slot) {
base::FilePath key_path = dir.AppendASCII(key_filename);
std::string key_pkcs8;
bool success = base::ReadFileToString(key_path, &key_pkcs8);
if (!success) {
LOG(ERROR) << "Failed to read file " << key_path.value();
return scoped_ptr<crypto::RSAPrivateKey>();
}
const uint8* key_pkcs8_begin =
reinterpret_cast<const uint8*>(key_pkcs8.data());
std::vector<uint8> key_vector(key_pkcs8_begin,
key_pkcs8_begin + key_pkcs8.length());
scoped_ptr<crypto::RSAPrivateKey> private_key(
crypto::RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(slot,
key_vector));
LOG_IF(ERROR, !private_key) << "Could not create key from file "
<< key_path.value();
return private_key.Pass();
}
} // namespace net
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment