summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-11 22:03:39 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-11 22:03:39 +0000
commit5c8e00570c198b8705f5674a1e18518a186f7fbb (patch)
treeebc85145c09acb9d45e6dd7ee0c967bd2e928db6 /net/base
parentc113e9510e7135107358db42397c0797c83ab12f (diff)
downloadchromium_src-5c8e00570c198b8705f5674a1e18518a186f7fbb.zip
chromium_src-5c8e00570c198b8705f5674a1e18518a186f7fbb.tar.gz
chromium_src-5c8e00570c198b8705f5674a1e18518a186f7fbb.tar.bz2
Add NSS PKCS12 import/export functions to CertDatabase.
Use sql: prefix when opening NSS UserDB (this will affect existing Chromeos installations, which had been using the old berkelydb format.) BUG=19991,51327,51328,51330,51332 TEST=net/base/cert_database_nss_unittest.cc Review URL: http://codereview.chromium.org/3018038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55798 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r--net/base/cert_database.h19
-rw-r--r--net/base/cert_database_nss.cc19
-rw-r--r--net/base/cert_database_nss_unittest.cc116
-rw-r--r--net/base/net_error_list.h7
4 files changed, 160 insertions, 1 deletions
diff --git a/net/base/cert_database.h b/net/base/cert_database.h
index 9621e45..a264f19 100644
--- a/net/base/cert_database.h
+++ b/net/base/cert_database.h
@@ -6,11 +6,17 @@
#define NET_BASE_CERT_DATABASE_H_
#pragma once
+#include <string>
+#include <vector>
+
#include "base/basictypes.h"
+#include "base/string16.h"
+#include "base/ref_counted.h"
namespace net {
class X509Certificate;
+typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
// This class provides functions to manipulate the local
// certificate store.
@@ -32,6 +38,19 @@ class CertDatabase {
// the platform cert database, or possibly other network error codes.
int AddUserCert(X509Certificate* cert);
+#if defined(USE_NSS)
+ // Import certificates and private keys from PKCS #12 blob.
+ // Returns OK or a network error code such as ERR_PKCS12_IMPORT_BAD_PASSWORD
+ // or ERR_PKCS12_IMPORT_ERROR.
+ int ImportFromPKCS12(const std::string& data, const string16& password);
+
+ // Export the given certificates and private keys into a PKCS #12 blob,
+ // storing into |output|.
+ // Returns the number of certificates successfully exported.
+ int ExportToPKCS12(const CertificateList& certs, const string16& password,
+ std::string* output);
+#endif
+
private:
DISALLOW_COPY_AND_ASSIGN(CertDatabase);
};
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc
index 98930ff..e314afa 100644
--- a/net/base/cert_database_nss.cc
+++ b/net/base/cert_database_nss.cc
@@ -13,15 +13,20 @@
#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
#include "base/logging.h"
-#include "base/scoped_ptr.h"
#include "base/nss_util.h"
+#include "base/scoped_ptr.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"
+#include "net/third_party/mozilla_security_manager/nsPKCS12Blob.h"
+
+// PSM = Mozilla's Personal Security Manager.
+namespace psm = mozilla_security_manager;
namespace net {
CertDatabase::CertDatabase() {
base::EnsureNSSInit();
+ psm::EnsurePKCS12Init();
}
int CertDatabase::CheckUserCert(X509Certificate* cert_obj) {
@@ -85,4 +90,16 @@ int CertDatabase::AddUserCert(X509Certificate* cert_obj) {
return OK;
}
+int CertDatabase::ImportFromPKCS12(
+ const std::string& data, const string16& password) {
+ return psm::nsPKCS12Blob_Import(data.data(), data.size(), password);
+}
+
+int CertDatabase::ExportToPKCS12(
+ const CertificateList& certs,
+ const string16& password,
+ std::string* output) {
+ return psm::nsPKCS12Blob_Export(output, certs, password);
+}
+
} // namespace net
diff --git a/net/base/cert_database_nss_unittest.cc b/net/base/cert_database_nss_unittest.cc
new file mode 100644
index 0000000..f25b043
--- /dev/null
+++ b/net/base/cert_database_nss_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2010 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 <cert.h>
+#include <pk11pub.h>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/nss_util.h"
+#include "base/nss_util_internal.h"
+#include "base/path_service.h"
+#include "base/scoped_temp_dir.h"
+#include "base/string_util.h"
+#include "net/base/cert_database.h"
+#include "net/base/net_errors.h"
+#include "net/base/x509_certificate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+// Returns a FilePath object representing the src/net/data/ssl/certificates
+// directory in the source tree.
+FilePath GetTestCertsDirectory() {
+ FilePath certs_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
+ certs_dir = certs_dir.AppendASCII("net");
+ certs_dir = certs_dir.AppendASCII("data");
+ certs_dir = certs_dir.AppendASCII("ssl");
+ certs_dir = certs_dir.AppendASCII("certificates");
+ return certs_dir;
+}
+
+} // namespace
+
+
+class CertDatabaseNSSTest : public testing::Test {
+ public:
+ virtual void SetUp() {
+ ASSERT_TRUE(temp_db_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(
+ base::OpenTestNSSDB(temp_db_dir_.path(), "CertDatabaseNSSTest db"));
+ }
+ virtual void TearDown() {
+ base::CloseTestNSSDB();
+ }
+ private:
+ ScopedTempDir temp_db_dir_;
+};
+
+TEST_F(CertDatabaseNSSTest, ImportFromPKCS12WrongPassword) {
+ PK11SlotInfo* slot = base::GetDefaultNSSKeySlot();
+ CertDatabase cert_db;
+
+ CERTCertList* cert_list = PK11_ListCertsInSlot(slot);
+ // Test db should be empty at start of test.
+ EXPECT_TRUE(CERT_LIST_END(CERT_LIST_HEAD(cert_list), cert_list));
+ CERT_DestroyCertList(cert_list);
+
+ FilePath cert_path = GetTestCertsDirectory().AppendASCII("client.p12");
+ std::string cert_data;
+ ASSERT_TRUE(file_util::ReadFileToString(cert_path, &cert_data));
+ EXPECT_EQ(ERR_PKCS12_IMPORT_BAD_PASSWORD,
+ cert_db.ImportFromPKCS12(cert_data, ASCIIToUTF16("")));
+
+
+ cert_list = PK11_ListCertsInSlot(slot);
+ // Test db should still be empty.
+ EXPECT_TRUE(CERT_LIST_END(CERT_LIST_HEAD(cert_list), cert_list));
+ CERT_DestroyCertList(cert_list);
+
+ PK11_FreeSlot(slot);
+}
+
+TEST_F(CertDatabaseNSSTest, ImportFromPKCS12AndExportAgain) {
+ PK11SlotInfo* slot = base::GetDefaultNSSKeySlot();
+ CertDatabase cert_db;
+
+ CERTCertList* cert_list = PK11_ListCertsInSlot(slot);
+ // Test db should be empty at start of test.
+ EXPECT_TRUE(CERT_LIST_END(CERT_LIST_HEAD(cert_list), cert_list));
+ CERT_DestroyCertList(cert_list);
+
+ FilePath cert_path = GetTestCertsDirectory().AppendASCII("client.p12");
+ std::string cert_data;
+ ASSERT_TRUE(file_util::ReadFileToString(cert_path, &cert_data));
+ EXPECT_EQ(OK, cert_db.ImportFromPKCS12(cert_data, ASCIIToUTF16("12345")));
+
+ cert_list = PK11_ListCertsInSlot(slot);
+ // Test db should be empty at start of test.
+ ASSERT_FALSE(CERT_LIST_END(CERT_LIST_HEAD(cert_list), cert_list));
+ scoped_refptr<X509Certificate> cert(
+ X509Certificate::CreateFromHandle(
+ CERT_LIST_HEAD(cert_list)->cert,
+ X509Certificate::SOURCE_LONE_CERT_IMPORT,
+ X509Certificate::OSCertHandles()));
+ CERT_DestroyCertList(cert_list);
+
+ EXPECT_EQ("testusercert",
+ cert->subject().common_name);
+
+ // TODO(mattm): move export test to seperate test case?
+ CertificateList certs;
+ certs.push_back(cert);
+ std::string exported_data;
+ EXPECT_EQ(1, cert_db.ExportToPKCS12(certs, ASCIIToUTF16("exportpw"),
+ &exported_data));
+ ASSERT_LT(0U, exported_data.size());
+ // TODO(mattm): further verification of exported data?
+
+ PK11_FreeSlot(slot);
+}
+
+} // namespace net
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 53849631..1a0e242 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -16,6 +16,7 @@
// 400-499 Cache errors
// 500-599 ?
// 600-699 FTP errors
+// 700-799 Certificate manager errors
//
// An asynchronous IO operation is not yet complete. This usually does not
@@ -420,3 +421,9 @@ NET_ERROR(FTP_COMMAND_NOT_SUPPORTED, -606)
// order.
// FTP response code 503.
NET_ERROR(FTP_BAD_COMMAND_SEQUENCE, -607)
+
+// PKCS #12 import failed due to incorrect password.
+NET_ERROR(PKCS12_IMPORT_BAD_PASSWORD, -701)
+
+// PKCS #12 import failed due to other error.
+NET_ERROR(PKCS12_IMPORT_FAILED, -702)