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

Side by Side Diff: net/cert/cert_verify_proc_builtin.cc

Issue 2829783002: [refactor] Extract the platform-specific TrustStore instantiations and (Closed)
Patch Set: delete bad comment Created 3 years, 8 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
« no previous file with comments | « net/BUILD.gn ('k') | net/cert/internal/system_trust_store.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/cert_verify_proc_builtin.h" 5 #include "net/cert/cert_verify_proc_builtin.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #if defined(USE_NSS_CERTS)
11 #include <cert.h>
12 #include <pk11pub.h>
13 #endif
14
15 #include "base/logging.h" 10 #include "base/logging.h"
16 #include "base/memory/ptr_util.h" 11 #include "base/memory/ptr_util.h"
17 #include "base/sha1.h" 12 #include "base/sha1.h"
18 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
19 #include "crypto/sha2.h" 14 #include "crypto/sha2.h"
20 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
21 #include "net/cert/asn1_util.h" 16 #include "net/cert/asn1_util.h"
22 #include "net/cert/cert_status_flags.h" 17 #include "net/cert/cert_status_flags.h"
23 #include "net/cert/cert_verify_proc.h" 18 #include "net/cert/cert_verify_proc.h"
24 #include "net/cert/cert_verify_result.h" 19 #include "net/cert/cert_verify_result.h"
25 #include "net/cert/internal/cert_errors.h" 20 #include "net/cert/internal/cert_errors.h"
26 #include "net/cert/internal/cert_issuer_source_static.h" 21 #include "net/cert/internal/cert_issuer_source_static.h"
27 #include "net/cert/internal/parsed_certificate.h" 22 #include "net/cert/internal/parsed_certificate.h"
28 #include "net/cert/internal/path_builder.h" 23 #include "net/cert/internal/path_builder.h"
29 #include "net/cert/internal/signature_policy.h" 24 #include "net/cert/internal/signature_policy.h"
30 #include "net/cert/internal/trust_store_collection.h" 25 #include "net/cert/internal/system_trust_store.h"
31 #include "net/cert/internal/trust_store_in_memory.h"
32 #include "net/cert/internal/verify_certificate_chain.h" 26 #include "net/cert/internal/verify_certificate_chain.h"
33 #include "net/cert/x509_certificate.h" 27 #include "net/cert/x509_certificate.h"
34 #include "net/cert/x509_util.h" 28 #include "net/cert/x509_util.h"
35 #include "net/der/encode_values.h" 29 #include "net/der/encode_values.h"
36 30
37 #if defined(USE_NSS_CERTS)
38 #include "crypto/nss_util.h"
39 #include "net/cert/internal/cert_issuer_source_nss.h"
40 #include "net/cert/internal/trust_store_nss.h"
41 #include "net/cert/scoped_nss_types.h"
42 #endif
43
44 namespace net { 31 namespace net {
45 32
46 namespace { 33 namespace {
47 34
48 class CertVerifyProcBuiltin : public CertVerifyProc { 35 class CertVerifyProcBuiltin : public CertVerifyProc {
49 public: 36 public:
50 CertVerifyProcBuiltin(); 37 CertVerifyProcBuiltin();
51 38
52 bool SupportsAdditionalTrustAnchors() const override; 39 bool SupportsAdditionalTrustAnchors() const override;
53 bool SupportsOCSPStapling() const override; 40 bool SupportsOCSPStapling() const override;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 CertErrors errors; 82 CertErrors errors;
96 for (auto it = cert_handles.begin(); it != cert_handles.end(); ++it) { 83 for (auto it = cert_handles.begin(); it != cert_handles.end(); ++it) {
97 scoped_refptr<ParsedCertificate> cert = 84 scoped_refptr<ParsedCertificate> cert =
98 ParseCertificateFromOSHandle(*it, &errors); 85 ParseCertificateFromOSHandle(*it, &errors);
99 if (cert) 86 if (cert)
100 intermediates->AddCert(std::move(cert)); 87 intermediates->AddCert(std::move(cert));
101 // TODO(crbug.com/634443): Surface these parsing errors? 88 // TODO(crbug.com/634443): Surface these parsing errors?
102 } 89 }
103 } 90 }
104 91
105 // The SystemTrustStore interface augments the TrustStore interface with some
106 // additional functionality:
107 //
108 // * Determine if a trust anchor was one of the known roots
109 // * Determine if a trust anchor was one of the "extra" ones that
110 // was specified during verification.
111 //
112 // Implementations of SystemTrustStore create an effective trust
113 // store that is the composition of:
114 //
115 // (1) System trust store
116 // (2) |additional_trust_anchors|.
117 // (3) Test certificates (if they are separate from system trust store)
118 class SystemTrustStore {
119 public:
120 virtual ~SystemTrustStore() {}
121
122 virtual TrustStore* GetTrustStore() = 0;
123
124 // TODO(eroman): Can this be exposed through the TrustStore
125 // interface instead?
126 virtual CertIssuerSource* GetCertIssuerSource() = 0;
127
128 // IsKnownRoot returns true if the given trust anchor is a standard one (as
129 // opposed to a user-installed root)
130 virtual bool IsKnownRoot(
131 const scoped_refptr<TrustAnchor>& trust_anchor) const = 0;
132
133 virtual bool IsAdditionalTrustAnchor(
134 const scoped_refptr<TrustAnchor>& trust_anchor) const = 0;
135 };
136
137 #if defined(USE_NSS_CERTS)
138 class SystemTrustStoreNSS : public SystemTrustStore {
139 public:
140 explicit SystemTrustStoreNSS(const CertificateList& additional_trust_anchors)
141 : trust_store_nss_(trustSSL) {
142 CertErrors errors;
143
144 trust_store_.AddTrustStore(&additional_trust_store_);
145 for (const auto& x509_cert : additional_trust_anchors) {
146 scoped_refptr<ParsedCertificate> cert =
147 ParseCertificateFromOSHandle(x509_cert->os_cert_handle(), &errors);
148 if (cert) {
149 additional_trust_store_.AddTrustAnchor(
150 TrustAnchor::CreateFromCertificateNoConstraints(std::move(cert)));
151 }
152 // TODO(eroman): Surface parsing errors of additional trust anchor.
153 }
154
155 trust_store_.AddTrustStore(&trust_store_nss_);
156 }
157
158 TrustStore* GetTrustStore() override { return &trust_store_; }
159
160 CertIssuerSource* GetCertIssuerSource() override {
161 return &cert_issuer_source_nss_;
162 }
163
164 // IsKnownRoot returns true if the given trust anchor is a standard one (as
165 // opposed to a user-installed root)
166 bool IsKnownRoot(
167 const scoped_refptr<TrustAnchor>& trust_anchor) const override {
168 // TODO(eroman): Based on how the TrustAnchors are created by this
169 // integration, there will always be an associated certificate. However this
170 // contradicts the API for TrustAnchor that states it is optional.
171 DCHECK(trust_anchor->cert());
172
173 // TODO(eroman): The overall approach of IsKnownRoot() is inefficient -- it
174 // requires searching for the trust anchor by DER in NSS, however path
175 // building already had a handle to it.
176 SECItem der_cert;
177 der_cert.data =
178 const_cast<uint8_t*>(trust_anchor->cert()->der_cert().UnsafeData());
179 der_cert.len = trust_anchor->cert()->der_cert().Length();
180 der_cert.type = siDERCertBuffer;
181 ScopedCERTCertificate nss_cert(
182 CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
183 if (!nss_cert)
184 return false;
185
186 return IsKnownRoot(nss_cert.get());
187 }
188
189 bool IsAdditionalTrustAnchor(
190 const scoped_refptr<TrustAnchor>& trust_anchor) const override {
191 return additional_trust_store_.Contains(trust_anchor.get());
192 }
193
194 private:
195 // TODO(eroman): This function was copied verbatim from
196 // cert_verify_proc_nss.cc
197 //
198 // IsKnownRoot returns true if the given certificate is one that we believe
199 // is a standard (as opposed to user-installed) root.
200 bool IsKnownRoot(CERTCertificate* root) const {
201 if (!root || !root->slot)
202 return false;
203
204 // This magic name is taken from
205 // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw /builtins/constants.c&rev=1.13&mark=86,89#79
206 return 0 == strcmp(PK11_GetSlotName(root->slot), "NSS Builtin Objects");
207 }
208
209 TrustStoreCollection trust_store_;
210 TrustStoreInMemory additional_trust_store_;
211
212 TrustStoreNSS trust_store_nss_;
213 CertIssuerSourceNSS cert_issuer_source_nss_;
214 };
215 #endif
216
217 std::unique_ptr<SystemTrustStore> CreateSystemTrustStore(
218 const CertificateList& additional_trust_anchors) {
219 #if defined(USE_NSS_CERTS)
220 return base::MakeUnique<SystemTrustStoreNSS>(additional_trust_anchors);
221 #else
222 // TODO(crbug.com/649017): Integrate with other system trust stores.
223 NOTIMPLEMENTED();
224 return nullptr;
225 #endif
226 }
227
228 // Appends the SHA1 and SHA256 hashes of |spki_bytes| to |*hashes|. 92 // Appends the SHA1 and SHA256 hashes of |spki_bytes| to |*hashes|.
229 void AppendPublicKeyHashes(const der::Input& spki_bytes, 93 void AppendPublicKeyHashes(const der::Input& spki_bytes,
230 HashValueVector* hashes) { 94 HashValueVector* hashes) {
231 HashValue sha1(HASH_VALUE_SHA1); 95 HashValue sha1(HASH_VALUE_SHA1);
232 base::SHA1HashBytes(spki_bytes.UnsafeData(), spki_bytes.Length(), 96 base::SHA1HashBytes(spki_bytes.UnsafeData(), spki_bytes.Length(),
233 sha1.data()); 97 sha1.data());
234 hashes->push_back(sha1); 98 hashes->push_back(sha1);
235 99
236 HashValue sha256(HASH_VALUE_SHA256); 100 HashValue sha256(HASH_VALUE_SHA256);
237 crypto::SHA256HashString(spki_bytes.AsStringPiece(), sha256.data(), 101 crypto::SHA256HashString(spki_bytes.AsStringPiece(), sha256.data(),
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 192
329 // Parse the target certificate. 193 // Parse the target certificate.
330 scoped_refptr<ParsedCertificate> target = ParseCertificateFromOSHandle( 194 scoped_refptr<ParsedCertificate> target = ParseCertificateFromOSHandle(
331 input_cert->os_cert_handle(), &parsing_errors); 195 input_cert->os_cert_handle(), &parsing_errors);
332 if (!target) { 196 if (!target) {
333 // TODO(crbug.com/634443): Surface these parsing errors? 197 // TODO(crbug.com/634443): Surface these parsing errors?
334 verify_result->cert_status |= CERT_STATUS_INVALID; 198 verify_result->cert_status |= CERT_STATUS_INVALID;
335 return; 199 return;
336 } 200 }
337 201
338 std::unique_ptr<SystemTrustStore> trust_store = 202 std::unique_ptr<SystemTrustStore> ssl_trust_store =
339 CreateSystemTrustStore(additional_trust_anchors); 203 CreateSslSystemTrustStore();
204
205 for (const auto& x509_cert : additional_trust_anchors) {
206 scoped_refptr<ParsedCertificate> cert = ParseCertificateFromOSHandle(
207 x509_cert->os_cert_handle(), &parsing_errors);
208 if (cert) {
209 ssl_trust_store->AddTrustAnchor(
210 TrustAnchor::CreateFromCertificateNoConstraints(std::move(cert)));
211 }
212 // TODO(eroman): Surface parsing errors of additional trust anchor.
213 }
340 214
341 // TODO(eroman): The path building code in this file enforces its idea of weak 215 // TODO(eroman): The path building code in this file enforces its idea of weak
342 // keys, and separately cert_verify_proc.cc also checks the chains with its 216 // keys, and separately cert_verify_proc.cc also checks the chains with its
343 // own policy. These policies should be aligned, to give path building the 217 // own policy. These policies should be aligned, to give path building the
344 // best chance of finding a good path. 218 // best chance of finding a good path.
345 // Another difference to resolve is the path building here does not check the 219 // Another difference to resolve is the path building here does not check the
346 // target certificate's key strength, whereas cert_verify_proc.cc does. 220 // target certificate's key strength, whereas cert_verify_proc.cc does.
347 SimpleSignaturePolicy signature_policy(1024); 221 SimpleSignaturePolicy signature_policy(1024);
348 222
349 // Use the current time. 223 // Use the current time.
350 der::GeneralizedTime verification_time; 224 der::GeneralizedTime verification_time;
351 if (!der::EncodeTimeAsGeneralizedTime(base::Time::Now(), 225 if (!der::EncodeTimeAsGeneralizedTime(base::Time::Now(),
352 &verification_time)) { 226 &verification_time)) {
353 // This really shouldn't be possible unless Time::Now() returned 227 // This really shouldn't be possible unless Time::Now() returned
354 // something crazy. 228 // something crazy.
355 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 229 verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
356 return; 230 return;
357 } 231 }
358 232
359 // Initialize the path builder. 233 // Initialize the path builder.
360 CertPathBuilder::Result result; 234 CertPathBuilder::Result result;
361 CertPathBuilder path_builder(target, trust_store->GetTrustStore(), 235 CertPathBuilder path_builder(target, ssl_trust_store->GetTrustStore(),
362 &signature_policy, verification_time, 236 &signature_policy, verification_time,
363 KeyPurpose::SERVER_AUTH, &result); 237 KeyPurpose::SERVER_AUTH, &result);
364 238
365 // Allow the path builder to discover intermediates from the trust store. 239 // Allow the path builder to discover intermediates from the trust store.
366 if (trust_store->GetCertIssuerSource()) 240 if (ssl_trust_store->GetCertIssuerSource())
367 path_builder.AddCertIssuerSource(trust_store->GetCertIssuerSource()); 241 path_builder.AddCertIssuerSource(ssl_trust_store->GetCertIssuerSource());
368 242
369 // Allow the path builder to discover the explicitly provided intermediates in 243 // Allow the path builder to discover the explicitly provided intermediates in
370 // |input_cert|. 244 // |input_cert|.
371 CertIssuerSourceStatic intermediates; 245 CertIssuerSourceStatic intermediates;
372 AddIntermediatesToIssuerSource(input_cert, &intermediates); 246 AddIntermediatesToIssuerSource(input_cert, &intermediates);
373 path_builder.AddCertIssuerSource(&intermediates); 247 path_builder.AddCertIssuerSource(&intermediates);
374 248
375 // TODO(crbug.com/649017): Allow the path builder to discover intermediates 249 // TODO(crbug.com/649017): Allow the path builder to discover intermediates
376 // through AIA fetching. 250 // through AIA fetching.
377 251
378 path_builder.Run(); 252 path_builder.Run();
379 253
380 if (result.best_result_index >= result.paths.size()) { 254 if (result.best_result_index >= result.paths.size()) {
381 // TODO(crbug.com/634443): What errors to communicate? Maybe the path 255 // TODO(crbug.com/634443): What errors to communicate? Maybe the path
382 // builder should always return some partial path (even if just containing 256 // builder should always return some partial path (even if just containing
383 // the target), then there is a CertErrors to test. 257 // the target), then there is a CertErrors to test.
384 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 258 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
385 return; 259 return;
386 } 260 }
387 261
388 // Use the best path that was built. This could be a partial path, or it could 262 // Use the best path that was built. This could be a partial path, or it could
389 // be a valid complete path. 263 // be a valid complete path.
390 const CertPathBuilder::ResultPath& partial_path = 264 const CertPathBuilder::ResultPath& partial_path =
391 *result.paths[result.best_result_index].get(); 265 *result.paths[result.best_result_index].get();
392 266
393 if (partial_path.path.trust_anchor) { 267 if (partial_path.path.trust_anchor) {
394 verify_result->is_issued_by_known_root = 268 verify_result->is_issued_by_known_root =
395 trust_store->IsKnownRoot(partial_path.path.trust_anchor); 269 ssl_trust_store->IsKnownRoot(partial_path.path.trust_anchor);
396 270
397 verify_result->is_issued_by_additional_trust_anchor = 271 verify_result->is_issued_by_additional_trust_anchor =
398 trust_store->IsAdditionalTrustAnchor(partial_path.path.trust_anchor); 272 ssl_trust_store->IsAdditionalTrustAnchor(
273 partial_path.path.trust_anchor);
399 } else { 274 } else {
400 // TODO(eroman): This shouldn't be necessary -- partial_path.errors should 275 // TODO(eroman): This shouldn't be necessary -- partial_path.errors should
401 // contain an error if it didn't chain to trust anchor. 276 // contain an error if it didn't chain to trust anchor.
402 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 277 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
403 } 278 }
404 279
405 verify_result->verified_cert = 280 verify_result->verified_cert =
406 CreateVerifiedCertChain(input_cert, partial_path); 281 CreateVerifiedCertChain(input_cert, partial_path);
407 282
408 AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes); 283 AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
(...skipping 27 matching lines...) Expand all
436 : OK; 311 : OK;
437 } 312 }
438 313
439 } // namespace 314 } // namespace
440 315
441 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin() { 316 scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin() {
442 return scoped_refptr<CertVerifyProc>(new CertVerifyProcBuiltin()); 317 return scoped_refptr<CertVerifyProc>(new CertVerifyProcBuiltin());
443 } 318 }
444 319
445 } // namespace net 320 } // namespace net
OLDNEW
« no previous file with comments | « net/BUILD.gn ('k') | net/cert/internal/system_trust_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698