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

Side by Side Diff: net/cert/internal/trust_store_nss.cc

Issue 2832703002: Allow the TrustStore interface to return matching intermediates, and identify distrusted certs. (Closed)
Patch Set: address comments Created 3 years, 7 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/internal/trust_store_nss.h" 5 #include "net/cert/internal/trust_store_nss.h"
6 6
7 #include <cert.h> 7 #include <cert.h>
8 #include <certdb.h> 8 #include <certdb.h>
9 9
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "crypto/nss_util.h" 11 #include "crypto/nss_util.h"
12 #include "net/cert/internal/cert_errors.h" 12 #include "net/cert/internal/cert_errors.h"
13 #include "net/cert/internal/parsed_certificate.h" 13 #include "net/cert/internal/parsed_certificate.h"
14 #include "net/cert/scoped_nss_types.h"
14 #include "net/cert/x509_util.h" 15 #include "net/cert/x509_util.h"
15 16
16 // TODO(mattm): structure so that supporting ChromeOS multi-profile stuff is 17 // TODO(mattm): structure so that supporting ChromeOS multi-profile stuff is
17 // doable (Have a TrustStoreChromeOS which uses net::NSSProfileFilterChromeOS, 18 // doable (Have a TrustStoreChromeOS which uses net::NSSProfileFilterChromeOS,
18 // similar to CertVerifyProcChromeOS.) 19 // similar to CertVerifyProcChromeOS.)
19 20
20 namespace net { 21 namespace net {
21 22
22 TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type) 23 TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type)
23 : trust_type_(trust_type) {} 24 : trust_type_(trust_type) {}
24 25
25 TrustStoreNSS::~TrustStoreNSS() = default; 26 TrustStoreNSS::~TrustStoreNSS() = default;
26 27
27 void TrustStoreNSS::FindTrustAnchorsForCert( 28 void TrustStoreNSS::SyncGetIssuersOf(const ParsedCertificate* cert,
28 const scoped_refptr<ParsedCertificate>& cert, 29 ParsedCertificateList* issuers) {
29 TrustAnchors* out_anchors) const {
30 crypto::EnsureNSSInit(); 30 crypto::EnsureNSSInit();
31 31
32 SECItem name; 32 SECItem name;
33 // Use the original issuer value instead of the normalized version. NSS does a 33 // Use the original issuer value instead of the normalized version. NSS does a
34 // less extensive normalization in its Name comparisons, so our normalized 34 // less extensive normalization in its Name comparisons, so our normalized
35 // version may not match the unnormalized version. 35 // version may not match the unnormalized version.
36 name.len = cert->tbs().issuer_tlv.Length(); 36 name.len = cert->tbs().issuer_tlv.Length();
37 name.data = const_cast<uint8_t*>(cert->tbs().issuer_tlv.UnsafeData()); 37 name.data = const_cast<uint8_t*>(cert->tbs().issuer_tlv.UnsafeData());
38 // |validOnly| in CERT_CreateSubjectCertList controls whether to return only 38 // |validOnly| in CERT_CreateSubjectCertList controls whether to return only
39 // certs that are valid at |sorttime|. Expiration isn't meaningful for trust 39 // certs that are valid at |sorttime|. Expiration isn't meaningful for trust
40 // anchors, so request all the matches. 40 // anchors, so request all the matches.
41 CERTCertList* found_certs = CERT_CreateSubjectCertList( 41 CERTCertList* found_certs = CERT_CreateSubjectCertList(
42 nullptr /* certList */, CERT_GetDefaultCertDB(), &name, 42 nullptr /* certList */, CERT_GetDefaultCertDB(), &name,
43 PR_Now() /* sorttime */, PR_FALSE /* validOnly */); 43 PR_Now() /* sorttime */, PR_FALSE /* validOnly */);
44 if (!found_certs) 44 if (!found_certs)
45 return; 45 return;
46 46
47 for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs); 47 for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs);
48 !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) { 48 !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) {
49 CERTCertTrust trust; 49 CertErrors parse_errors;
50 if (CERT_GetCertTrust(node->cert, &trust) != SECSuccess) 50 scoped_refptr<ParsedCertificate> cur_cert = ParsedCertificate::Create(
51 continue;
52
53 // TODO(mattm): handle explicit distrust (blacklisting)?
54 const int ca_trust = CERTDB_TRUSTED_CA;
55 if ((SEC_GET_TRUST_FLAGS(&trust, trust_type_) & ca_trust) != ca_trust)
56 continue;
57
58 CertErrors errors;
59 scoped_refptr<ParsedCertificate> anchor_cert = ParsedCertificate::Create(
60 x509_util::CreateCryptoBuffer(node->cert->derCert.data, 51 x509_util::CreateCryptoBuffer(node->cert->derCert.data,
61 node->cert->derCert.len), 52 node->cert->derCert.len),
62 {}, &errors); 53 {}, &parse_errors);
63 if (!anchor_cert) { 54
55 if (!cur_cert) {
64 // TODO(crbug.com/634443): return errors better. 56 // TODO(crbug.com/634443): return errors better.
65 LOG(ERROR) << "Error parsing issuer certificate:\n" 57 LOG(ERROR) << "Error parsing issuer certificate:\n"
66 << errors.ToDebugString(); 58 << parse_errors.ToDebugString();
67 continue; 59 continue;
68 } 60 }
69 61
70 out_anchors->push_back(TrustAnchor::CreateFromCertificateNoConstraints( 62 issuers->push_back(std::move(cur_cert));
71 std::move(anchor_cert)));
72 } 63 }
73 CERT_DestroyCertList(found_certs); 64 CERT_DestroyCertList(found_certs);
74 } 65 }
75 66
67 void TrustStoreNSS::GetTrust(const scoped_refptr<ParsedCertificate>& cert,
68 CertificateTrust* out_trust) const {
69 // TODO(eroman): Inefficient -- path building will convert between
70 // CERTCertificate and ParsedCertificate representations multiple times
71 // (when getting the issuers, and again here).
72
73 // Lookup the certificate by Issuer + Serial number. Note that
74 // CERT_FindCertByDERCert() doesn't check for equal DER, just matching issuer
75 // + serial number.
76 SECItem der_cert;
77 der_cert.data = const_cast<uint8_t*>(cert->der_cert().UnsafeData());
78 der_cert.len = cert->der_cert().Length();
79 der_cert.type = siDERCertBuffer;
80 ScopedCERTCertificate nss_matched_cert(
81 CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
82 if (!nss_matched_cert) {
83 *out_trust = CertificateTrust::ForUnspecified();
84 return;
85 }
86
87 // Determine the trustedness of the matched certificate.
88 CERTCertTrust trust;
89 if (CERT_GetCertTrust(nss_matched_cert.get(), &trust) != SECSuccess) {
90 *out_trust = CertificateTrust::ForUnspecified();
91 return;
92 }
93
94 // TODO(eroman): Determine if |nss_matched_cert| is distrusted.
95
96 // Determine if the certificate is a trust anchor.
97 const int ca_trust = CERTDB_TRUSTED_CA;
98 bool is_trusted =
99 (SEC_GET_TRUST_FLAGS(&trust, trust_type_) & ca_trust) == ca_trust;
100
101 // To consider |cert| trusted, need to additionally check that
102 // |cert| is the same as |nss_matched_cert|. This is because the lookup in NSS
103 // was only by issuer + serial number, so could be for a different
104 // SPKI.
105 if (is_trusted &&
106 (cert->der_cert() == der::Input(nss_matched_cert->derCert.data,
107 nss_matched_cert->derCert.len))) {
108 *out_trust = CertificateTrust::ForTrustAnchor();
109 return;
110 }
111
112 *out_trust = CertificateTrust::ForUnspecified();
113 return;
114 }
115
76 } // namespace net 116 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698