diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 16:58:37 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 16:58:37 +0000 |
commit | a755e1076f116a71e2888eeea635082baabc69ce (patch) | |
tree | 2dde81e236a55d88d7768495e78194df72a59550 /net/base/cert_database_nss.cc | |
parent | a5684464f46687c95ff8e62b48de4d09b914873d (diff) | |
download | chromium_src-a755e1076f116a71e2888eeea635082baabc69ce.zip chromium_src-a755e1076f116a71e2888eeea635082baabc69ce.tar.gz chromium_src-a755e1076f116a71e2888eeea635082baabc69ce.tar.bz2 |
Adds support for the <keygen> tag for client certificate enrollment
under Linux. Currently, no notifications are given to the user that the
certificate was successfully enrolled.
Patch by Gaurav Shah <gauravsh@chromium.org> of Google.
Original review URL: http://codereview.chromium.org/261035
BUG=148
TEST=Can test on the following sites:
http://foaf.me/simple_KEYGEN_CreateClientCertificate.php
http://www.myopenid.com
Review URL: http://codereview.chromium.org/271112
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29900 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/cert_database_nss.cc')
-rw-r--r-- | net/base/cert_database_nss.cc | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc new file mode 100644 index 0000000..5f43fef --- /dev/null +++ b/net/base/cert_database_nss.cc @@ -0,0 +1,102 @@ +// Copyright (c) 2009 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/base/cert_database.h" + +// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 +// until NSS 3.12.2 comes out and we update to it. +#define Lock FOO_NSS_Lock +#include <pk11pub.h> +#include <secmod.h> +#include <ssl.h> +#include <nssb64.h> // NSSBase64_EncodeItem() +#include <secder.h> // DER_Encode() +#include <cryptohi.h> // SEC_DerSignData() +#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() +#undef Lock + +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "base/nss_init.h" + +namespace net { + +CertDatabase::CertDatabase() { + Init(); +} + +bool CertDatabase::AddUserCert(const char* data, int len) { + CERTCertificate* cert = NULL; + PK11SlotInfo* slot = NULL; + std::string nickname; + bool is_success = true; + + // Make a copy of "data" since CERT_DecodeCertPackage + // might modify it. + char* data_copy = new char[len]; + memcpy(data_copy, data, len); + + // Parse into a certificate structure. + cert = CERT_DecodeCertFromPackage(data_copy, len); + delete [] data_copy; + if (!cert) { + LOG(ERROR) << "Couldn't create a temporary certificate"; + return false; + } + + // Check if the private key corresponding to the certificate exist + // We shouldn't accept any random client certificate sent by a CA. + + // Note: The NSS source documentation wrongly suggests that this + // also imports the certificate if the private key exists. This + // doesn't seem to be the case. + + slot = PK11_KeyForCertExists(cert, NULL, NULL); + if (!slot) { + LOG(ERROR) << "No corresponding private key in store"; + CERT_DestroyCertificate(cert); + return false; + } + PK11_FreeSlot(slot); + slot = NULL; + + // TODO(gauravsh): We also need to make sure another certificate + // doesn't already exist for the same private key. + + // Create a nickname for this certificate. + // We use the scheme used by Firefox: + // --> <subject's common name>'s <issuer's common name> ID. + // + + std::string username, ca_name; + char* temp_username = CERT_GetCommonName(&cert->subject); + char* temp_ca_name = CERT_GetCommonName(&cert->issuer); + if (temp_username) { + username = temp_username; + PORT_Free(temp_username); + } + if (temp_ca_name) { + ca_name = temp_ca_name; + PORT_Free(temp_ca_name); + } + nickname = username + "'s " + ca_name + " ID"; + + slot = PK11_ImportCertForKey(cert, + const_cast<char*>(nickname.c_str()), + NULL); + if (slot) { + PK11_FreeSlot(slot); + } else { + LOG(ERROR) << "Couldn't import user certificate."; + is_success = false; + } + CERT_DestroyCertificate(cert); + return is_success; +} + +void CertDatabase::Init() { + base::EnsureNSSInit(); +} + +} // namespace net |