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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cert/x509_util_win.h"
6
7 #include "crypto/scoped_capi_types.h"
8 #include "crypto/sha2.h"
9 #include "net/cert/x509_certificate.h"
10 #include "net/net_features.h"
11 #include "third_party/boringssl/src/include/openssl/pool.h"
12
13 namespace net {
14
15 namespace x509_util {
16
17 namespace {
18
19 typedef crypto::ScopedCAPIHandle<
20 HCERTSTORE,
21 crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0>>
davidben 2017/06/15 23:55:18 Nit: using
mattm 2017/06/16 21:39:31 Done.
22 ScopedHCERTSTORE;
23
24 } // namespace
25
26 scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
27 PCCERT_CONTEXT os_cert,
28 const std::vector<PCCERT_CONTEXT>& os_chain) {
29 #if BUILDFLAG(USE_BYTE_CERTS)
30 if (!os_cert || !os_cert->pbCertEncoded || !os_cert->cbCertEncoded)
31 return nullptr;
32 bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
33 X509Certificate::CreateOSCertHandleFromBytes(
34 reinterpret_cast<const char*>(os_cert->pbCertEncoded),
35 os_cert->cbCertEncoded));
36 if (!cert_handle)
37 return nullptr;
38 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
39 X509Certificate::OSCertHandles intermediates_raw;
40 for (PCCERT_CONTEXT os_intermediate : os_chain) {
41 if (!os_intermediate || !os_intermediate->pbCertEncoded ||
42 !os_intermediate->cbCertEncoded)
43 return nullptr;
44 bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
45 X509Certificate::CreateOSCertHandleFromBytes(
46 reinterpret_cast<const char*>(os_intermediate->pbCertEncoded),
47 os_intermediate->cbCertEncoded));
48 if (!intermediate_cert_handle)
49 return nullptr;
50 intermediates_raw.push_back(intermediate_cert_handle.get());
51 intermediates.push_back(std::move(intermediate_cert_handle));
52 }
53 scoped_refptr<X509Certificate> result(
54 X509Certificate::CreateFromHandle(cert_handle.get(), intermediates_raw));
55 return result;
56 #else
57 return X509Certificate::CreateFromHandle(os_cert, os_chain);
58 #endif
59 }
60
61 ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) {
62 // Create an in-memory certificate store to hold the certificate and its
63 // intermediate certificates. The store will be referenced in the returned
64 // PCCERT_CONTEXT, and will not be freed until the PCCERT_CONTEXT is freed.
65 ScopedHCERTSTORE store(
66 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL,
67 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL));
68 if (!store.get())
69 return nullptr;
70
71 PCCERT_CONTEXT primary_cert = nullptr;
72
73 #if BUILDFLAG(USE_BYTE_CERTS)
74 BOOL ok = CertAddEncodedCertificateToStore(
75 store.get(), X509_ASN_ENCODING,
76 reinterpret_cast<const BYTE*>(CRYPTO_BUFFER_data(cert->os_cert_handle())),
davidben 2017/06/15 23:55:18 Optional: It's probably safe to assume this cast i
mattm 2017/06/16 21:39:31 Done.
77 base::checked_cast<DWORD>(CRYPTO_BUFFER_len(cert->os_cert_handle())),
78 CERT_STORE_ADD_ALWAYS, &primary_cert);
79 if (!ok || !primary_cert)
80 return nullptr;
81 ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
82
83 for (X509Certificate::OSCertHandle intermediate :
84 cert->GetIntermediateCertificates()) {
85 ok = CertAddEncodedCertificateToStore(
86 store.get(), X509_ASN_ENCODING,
87 reinterpret_cast<const BYTE*>(CRYPTO_BUFFER_data(intermediate)),
88 base::checked_cast<DWORD>(CRYPTO_BUFFER_len(intermediate)),
89 CERT_STORE_ADD_ALWAYS, NULL);
90 if (!ok)
91 return nullptr;
92 }
93 #else
94 PCCERT_CONTEXT os_cert_handle = cert->os_cert_handle();
95 const std::vector<PCCERT_CONTEXT>& intermediate_ca_certs =
96 cert->GetIntermediateCertificates();
97
98 // NOTE: This preserves all of the properties of |os_cert_handle| except
99 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two
100 // properties that hold access to already-opened private keys. If a handle
101 // has already been unlocked (eg: PIN prompt), then the first time that the
102 // identity is used for client auth, it may prompt the user again.
103 BOOL ok = CertAddCertificateContextToStore(
104 store.get(), os_cert_handle, CERT_STORE_ADD_ALWAYS, &primary_cert);
105 if (!ok || !primary_cert)
106 return nullptr;
107 ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
108
109 for (size_t i = 0; i < intermediate_ca_certs.size(); ++i) {
davidben 2017/06/15 23:55:18 Nit: for (PCCERT_CONTEXT intermediate : intermedia
mattm 2017/06/16 21:39:31 Done.
110 CertAddCertificateContextToStore(store.get(), intermediate_ca_certs[i],
111 CERT_STORE_ADD_ALWAYS, NULL);
112 }
113 #endif
114
115 // Note: |store| is explicitly not released, as the call to CertCloseStore()
116 // when |store| goes out of scope will not actually free the store. Instead,
117 // the store will be freed when |primary_cert| is freed.
davidben 2017/06/15 23:55:18 This comment confuses me a little. It reads like y
mattm 2017/06/16 21:39:31 Done.
118 return scoped_primary_cert;
119 }
120
121 SHA256HashValue CalculateFingerprint256(PCCERT_CONTEXT cert) {
122 DCHECK(NULL != cert->pbCertEncoded);
123 DCHECK_NE(0u, cert->cbCertEncoded);
124
125 SHA256HashValue sha256;
126 size_t sha256_size = sizeof(sha256.data);
davidben 2017/06/15 23:55:18 Nit: Any reason to stash this into a variable? You
mattm 2017/06/16 21:39:31 Done.
127
128 // Use crypto::SHA256HashString for two reasons:
129 // * < Windows Vista does not have universal SHA-256 support.
130 // * More efficient on Windows > Vista (less overhead since non-default CSP
131 // is not needed).
132 base::StringPiece der_cert(reinterpret_cast<const char*>(cert->pbCertEncoded),
133 cert->cbCertEncoded);
134 crypto::SHA256HashString(der_cert, sha256.data, sha256_size);
135 return sha256;
136 }
137
138 bool IsSelfSigned(PCCERT_CONTEXT cert_handle) {
139 bool valid_signature = !!CryptVerifyCertificateSignatureEx(
140 NULL, X509_ASN_ENCODING, CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
141 reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)),
142 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT,
143 reinterpret_cast<void*>(const_cast<PCERT_CONTEXT>(cert_handle)), 0, NULL);
144 if (!valid_signature)
145 return false;
146 return !!CertCompareCertificateName(X509_ASN_ENCODING,
147 &cert_handle->pCertInfo->Subject,
148 &cert_handle->pCertInfo->Issuer);
149 }
150
151 } // namespace x509_util
152
153 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698