Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Unified Diff: net/cert/x509_util_win.cc

Issue 2913253003: Convert Windows to use X509CertificateBytes. (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/cert/x509_util_win.h ('k') | net/data/parse_certificate_unittest/signature_algorithm_null.pem » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/cert/x509_util_win.cc
diff --git a/net/cert/x509_util_win.cc b/net/cert/x509_util_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4b1f74df4ced351fd92308eacc991aecbb98c11b
--- /dev/null
+++ b/net/cert/x509_util_win.cc
@@ -0,0 +1,149 @@
+// Copyright 2017 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/cert/x509_util_win.h"
+
+#include "crypto/scoped_capi_types.h"
+#include "crypto/sha2.h"
+#include "net/cert/x509_certificate.h"
+#include "net/net_features.h"
+#include "third_party/boringssl/src/include/openssl/pool.h"
+
+namespace net {
+
+namespace x509_util {
+
+namespace {
+
+using ScopedHCERTSTORE = crypto::ScopedCAPIHandle<
+ HCERTSTORE,
+ crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0>>;
+
+} // namespace
+
+scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
+ PCCERT_CONTEXT os_cert,
+ const std::vector<PCCERT_CONTEXT>& os_chain) {
+#if BUILDFLAG(USE_BYTE_CERTS)
+ if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded)
+ return nullptr;
+ bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
+ X509Certificate::CreateOSCertHandleFromBytes(
+ reinterpret_cast<const char*>(os_cert->pbCertEncoded),
+ os_cert->cbCertEncoded));
+ if (!cert_handle)
+ return nullptr;
+ std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
+ X509Certificate::OSCertHandles intermediates_raw;
+ for (PCCERT_CONTEXT os_intermediate : os_chain) {
+ if (!os_intermediate || !os_intermediate->pbCertEncoded ||
+ !os_intermediate->cbCertEncoded)
+ return nullptr;
+ bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
+ X509Certificate::CreateOSCertHandleFromBytes(
+ reinterpret_cast<const char*>(os_intermediate->pbCertEncoded),
+ os_intermediate->cbCertEncoded));
+ if (!intermediate_cert_handle)
+ return nullptr;
+ intermediates_raw.push_back(intermediate_cert_handle.get());
+ intermediates.push_back(std::move(intermediate_cert_handle));
+ }
+ scoped_refptr<X509Certificate> result(
+ X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw));
+ return result;
+#else
+ return X509Certificate::CreateFromHandle(os_cert, os_chain);
+#endif
+}
+
+ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) {
+ // Create an in-memory certificate store to hold the certificate and its
+ // intermediate certificates. The store will be referenced in the returned
+ // PCCERT_CONTEXT, and will not be freed until the PCCERT_CONTEXT is freed.
+ ScopedHCERTSTORE store(
+ CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL,
+ CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
+ if (!store.get())
+ return nullptr;
+
+ PCCERT_CONTEXT primary_cert = nullptr;
+
+#if BUILDFLAG(USE_BYTE_CERTS)
+ BOOL ok = CertAddEncodedCertificateToStore(
+ store.get(), X509_ASN_ENCODING,
+ CRYPTO_BUFFER_data(cert->os_cert_handle()),
+ base::checked_cast<DWORD>(CRYPTO_BUFFER_len(cert->os_cert_handle())),
+ CERT_STORE_ADD_ALWAYS, &primary_cert);
+ if (!ok || !primary_cert)
+ return nullptr;
+ ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
+
+ for (X509Certificate::OSCertHandle intermediate :
+ cert->GetIntermediateCertificates()) {
+ ok = CertAddEncodedCertificateToStore(
+ store.get(), X509_ASN_ENCODING, CRYPTO_BUFFER_data(intermediate),
+ base::checked_cast<DWORD>(CRYPTO_BUFFER_len(intermediate)),
+ CERT_STORE_ADD_ALWAYS, NULL);
+ if (!ok)
+ return nullptr;
+ }
+#else
+ PCCERT_CONTEXT os_cert_handle = cert->os_cert_handle();
+ const std::vector<PCCERT_CONTEXT>& intermediate_ca_certs =
+ cert->GetIntermediateCertificates();
+
+ // NOTE: This preserves all of the properties of |os_cert_handle| except
+ // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
+ // properties that hold access to already-opened private keys. If a handle
+ // has already been unlocked (eg: PIN prompt), then the first time that the
+ // identity is used for client auth, it may prompt the user again.
+ BOOL ok = CertAddCertificateContextToStore(
+ store.get(), os_cert_handle, CERT_STORE_ADD_ALWAYS, &primary_cert);
+ if (!ok || !primary_cert)
+ return nullptr;
+ ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
+
+ for (PCCERT_CONTEXT intermediate : intermediate_ca_certs) {
+ CertAddCertificateContextToStore(store.get(), intermediate,
+ CERT_STORE_ADD_ALWAYS, NULL);
+ }
+#endif
+
+ // Note: |primary_cert| retains a reference to |store|, so the store will
+ // actually be freed when |primary_cert| is freed.
+ return scoped_primary_cert;
+}
+
+SHA256HashValue CalculateFingerprint256(PCCERT_CONTEXT cert) {
+ DCHECK(NULL != cert->pbCertEncoded);
+ DCHECK_NE(0u, cert->cbCertEncoded);
+
+ SHA256HashValue sha256;
+
+ // Use crypto::SHA256HashString for two reasons:
+ // * < Windows Vista does not have universal SHA-256 support.
+ // * More efficient on Windows > Vista (less overhead since non-default CSP
+ // is not needed).
+ base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
+ cert->cbCertEncoded);
+ crypto::SHA256HashString(der_cert, sha256.data, sizeof(sha256.data));
+ return sha256;
+}
+
+bool IsSelfSigned(PCCERT_CONTEXT cert_handle) {
+ bool valid_signature = !!CryptVerifyCertificateSignatureEx(
+ NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
+ reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)),
+ CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
+ reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), 0, NULL);
+ if (!valid_signature)
+ return false;
+ return !!CertCompareCertificateName(X509_ASN_ENCODING,
+ &cert_handle->pCertInfo->Subject,
+ &cert_handle->pCertInfo->Issuer);
+}
+
+} // namespace x509_util
+
+} // namespace net
« no previous file with comments | « net/cert/x509_util_win.h ('k') | net/data/parse_certificate_unittest/signature_algorithm_null.pem » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698