summaryrefslogtreecommitdiffstats
path: root/net/base/cert_database_win.cc
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-01 18:49:47 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-01 18:49:47 +0000
commit9aed77b6dace047bff676a7cdcfef345a858d1a7 (patch)
treefddd5e0fac4ee39b6c79af56871f022472f276d9 /net/base/cert_database_win.cc
parent2779491e15b4a157b6351e20bb0f2dd26f6d84de (diff)
downloadchromium_src-9aed77b6dace047bff676a7cdcfef345a858d1a7.zip
chromium_src-9aed77b6dace047bff676a7cdcfef345a858d1a7.tar.gz
chromium_src-9aed77b6dace047bff676a7cdcfef345a858d1a7.tar.bz2
Adds support for the <keygen> element to Windows, matching
support present on Linux and Mac OS X. Contributed by Ryan Sleevi <ryan.sleevi@gmail.com>. Original review URL: http://codereview.chromium.org/843005 R=wtc BUG=148 TEST=KeygenHandler.SmokeTest Review URL: http://codereview.chromium.org/1591006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43365 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/cert_database_win.cc')
-rw-r--r--net/base/cert_database_win.cc110
1 files changed, 101 insertions, 9 deletions
diff --git a/net/base/cert_database_win.cc b/net/base/cert_database_win.cc
index 7e9d862..34485b5 100644
--- a/net/base/cert_database_win.cc
+++ b/net/base/cert_database_win.cc
@@ -1,30 +1,122 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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 "net/base/cert_database.h"
+#include <windows.h>
+#include <wincrypt.h>
+#pragma comment(lib, "crypt32.lib")
+
#include "base/logging.h"
+#include "base/string_util.h"
+#include "net/base/keygen_handler.h"
#include "net/base/net_errors.h"
+#include "net/base/x509_certificate.h"
namespace net {
+namespace {
+
+// Returns an encoded version of SubjectPublicKeyInfo from |cert| that is
+// compatible with KeygenHandler::Cache. If the cert cannot be converted, an
+// empty string is returned.
+std::string GetSubjectPublicKeyInfo(const X509Certificate* cert) {
+ DCHECK(cert);
+
+ std::string result;
+ if (!cert->os_cert_handle() || !cert->os_cert_handle()->pCertInfo)
+ return result;
+
+ BOOL ok;
+ DWORD size = 0;
+ PCERT_PUBLIC_KEY_INFO key_info =
+ &(cert->os_cert_handle()->pCertInfo->SubjectPublicKeyInfo);
+ ok = CryptEncodeObject(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, key_info,
+ NULL, &size);
+ if (!ok)
+ return result;
+
+ ok = CryptEncodeObject(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, key_info,
+ reinterpret_cast<BYTE*>(WriteInto(&result, size + 1)),
+ &size);
+ if (!ok) {
+ result.clear();
+ return result;
+ }
+
+ // Per MSDN, the resultant structure may be smaller than the original size
+ // supplied, so shrink to the actual size output.
+ result.resize(size);
+
+ return result;
+}
+
+// Returns true if |cert| was successfully modified to reference |location| to
+// obtain the associated private key.
+bool LinkCertToPrivateKey(X509Certificate* cert,
+ KeygenHandler::KeyLocation location) {
+ DCHECK(cert);
+
+ CRYPT_KEY_PROV_INFO prov_info = { 0 };
+ prov_info.pwszContainerName =
+ const_cast<LPWSTR>(location.container_name.c_str());
+ prov_info.pwszProvName =
+ const_cast<LPWSTR>(location.provider_name.c_str());
+
+ // Implicit by it being from KeygenHandler, which only supports RSA keys.
+ prov_info.dwProvType = PROV_RSA_FULL;
+ prov_info.dwKeySpec = AT_KEYEXCHANGE;
+
+ BOOL ok = CertSetCertificateContextProperty(cert->os_cert_handle(),
+ CERT_KEY_PROV_INFO_PROP_ID, 0,
+ &prov_info);
+ return ok != FALSE;
+}
+
+} // namespace
+
CertDatabase::CertDatabase() {
- NOTIMPLEMENTED();
}
int CertDatabase::CheckUserCert(X509Certificate* cert) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
+ if (!cert)
+ return ERR_CERT_INVALID;
+ if (cert->HasExpired())
+ return ERR_CERT_DATE_INVALID;
+
+ std::string encoded_info = GetSubjectPublicKeyInfo(cert);
+ KeygenHandler::Cache* cache = KeygenHandler::Cache::GetInstance();
+ KeygenHandler::KeyLocation location;
+
+ if (encoded_info.empty() || !cache->Find(encoded_info, &location) ||
+ !LinkCertToPrivateKey(cert, location))
+ return ERR_NO_PRIVATE_KEY_FOR_CERT;
+
+ return OK;
}
int CertDatabase::AddUserCert(X509Certificate* cert) {
- NOTIMPLEMENTED();
- return ERR_NOT_IMPLEMENTED;
-}
+ // TODO(rsleevi): Would it be more appropriate to have the CertDatabase take
+ // construction parameters (Keychain filepath on Mac OS X, PKCS #11 slot on
+ // NSS, and Store Type / Path) here? For now, certs will be stashed into the
+ // user's personal store, which will not automatically mark them as trusted,
+ // but will allow them to be used for client auth.
+ HCERTSTORE cert_db = CertOpenSystemStore(NULL, L"MY");
+ if (!cert_db)
+ return ERR_ADD_USER_CERT_FAILED;
+
+ BOOL added = CertAddCertificateContextToStore(cert_db,
+ cert->os_cert_handle(),
+ CERT_STORE_ADD_USE_EXISTING,
+ NULL);
+
+ CertCloseStore(cert_db, 0);
+
+ if (!added)
+ return ERR_ADD_USER_CERT_FAILED;
-void CertDatabase::Init() {
- NOTIMPLEMENTED();
+ return OK;
}
} // namespace net