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/internal/trust_store_nss_unittest.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 "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "crypto/scoped_test_nss_db.h" 12 #include "crypto/scoped_test_nss_db.h"
13 #include "net/cert/internal/cert_issuer_source_sync_unittest.h"
13 #include "net/cert/internal/test_helpers.h" 14 #include "net/cert/internal/test_helpers.h"
14 #include "net/cert/scoped_nss_types.h" 15 #include "net/cert/scoped_nss_types.h"
15 #include "net/cert/x509_certificate.h" 16 #include "net/cert/x509_certificate.h"
16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
17 18
18 namespace net { 19 namespace net {
19 20
20 namespace { 21 namespace {
21 22
22 class TrustStoreNSSTest : public testing::Test { 23 class TrustStoreNSSTest : public testing::Test {
23 public: 24 public:
24 void SetUp() override { 25 void SetUp() override {
25 ASSERT_TRUE(test_nssdb_.is_open()); 26 ASSERT_TRUE(test_nssdb_.is_open());
26 27
27 VerifyCertChainTest test; 28 VerifyCertChainTest test;
28 ParsedCertificateList chain; 29 ParsedCertificateList chain;
29 ReadVerifyCertChainTestFromFile( 30 ReadVerifyCertChainTestFromFile(
30 "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem", 31 "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem",
31 &test); 32 &test);
32 chain = test.chain; 33 chain = test.chain;
33 oldroot_ = test.trust_anchor;
34 34
35 ASSERT_EQ(2U, chain.size()); 35 ASSERT_EQ(3U, chain.size());
36 target_ = chain[0]; 36 target_ = chain[0];
37 oldintermediate_ = chain[1]; 37 oldintermediate_ = chain[1];
38 oldroot_ = chain[2];
38 ASSERT_TRUE(target_); 39 ASSERT_TRUE(target_);
39 ASSERT_TRUE(oldintermediate_); 40 ASSERT_TRUE(oldintermediate_);
40 ASSERT_TRUE(oldroot_); 41 ASSERT_TRUE(oldroot_);
41 42
42 ReadVerifyCertChainTestFromFile( 43 ReadVerifyCertChainTestFromFile(
43 "net/data/verify_certificate_chain_unittest/" 44 "net/data/verify_certificate_chain_unittest/"
44 "key-rollover-longrolloverchain.pem", 45 "key-rollover-longrolloverchain.pem",
45 &test); 46 &test);
46 chain = test.chain; 47 chain = test.chain;
47 48
48 ASSERT_EQ(4U, chain.size()); 49 ASSERT_EQ(5U, chain.size());
49 newintermediate_ = chain[1]; 50 newintermediate_ = chain[1];
50 newroot_ = TrustAnchor::CreateFromCertificateNoConstraints(chain[2]); 51 newroot_ = chain[2];
51 newrootrollover_ = chain[3]; 52 newrootrollover_ = chain[3];
52 ASSERT_TRUE(newintermediate_); 53 ASSERT_TRUE(newintermediate_);
53 ASSERT_TRUE(newroot_); 54 ASSERT_TRUE(newroot_);
54 ASSERT_TRUE(newrootrollover_); 55 ASSERT_TRUE(newrootrollover_);
55 56
56 trust_store_nss_.reset(new TrustStoreNSS(trustSSL)); 57 trust_store_nss_.reset(new TrustStoreNSS(trustSSL));
57 } 58 }
58 59
59 std::string GetUniqueNickname() { 60 std::string GetUniqueNickname() {
60 return "trust_store_nss_unittest" + base::UintToString(nickname_counter_++); 61 return "trust_store_nss_unittest" + base::UintToString(nickname_counter_++);
61 } 62 }
62 63
63 void AddCertToNSS(const ParsedCertificate* cert) { 64 void AddCertToNSS(const ParsedCertificate* cert) {
64 std::string nickname = GetUniqueNickname(); 65 std::string nickname = GetUniqueNickname();
65 ScopedCERTCertificate nss_cert( 66 ScopedCERTCertificate nss_cert(
66 X509Certificate::CreateOSCertHandleFromBytesWithNickname( 67 X509Certificate::CreateOSCertHandleFromBytesWithNickname(
67 cert->der_cert().AsStringPiece().data(), cert->der_cert().Length(), 68 cert->der_cert().AsStringPiece().data(), cert->der_cert().Length(),
68 nickname.c_str())); 69 nickname.c_str()));
69 ASSERT_TRUE(nss_cert); 70 ASSERT_TRUE(nss_cert);
70 SECStatus srv = 71 SECStatus srv =
71 PK11_ImportCert(test_nssdb_.slot(), nss_cert.get(), CK_INVALID_HANDLE, 72 PK11_ImportCert(test_nssdb_.slot(), nss_cert.get(), CK_INVALID_HANDLE,
72 nickname.c_str(), PR_FALSE /* includeTrust (unused) */); 73 nickname.c_str(), PR_FALSE /* includeTrust (unused) */);
73 ASSERT_EQ(SECSuccess, srv); 74 ASSERT_EQ(SECSuccess, srv);
74 } 75 }
75 76
76 void AddCertsToNSS() { 77 void AddCertsToNSS() {
77 AddCertToNSS(target_.get()); 78 AddCertToNSS(target_.get());
78 AddCertToNSS(oldintermediate_.get()); 79 AddCertToNSS(oldintermediate_.get());
79 AddCertToNSS(newintermediate_.get()); 80 AddCertToNSS(newintermediate_.get());
80 AddCertToNSS(oldroot_->cert().get()); 81 AddCertToNSS(oldroot_.get());
81 AddCertToNSS(newroot_->cert().get()); 82 AddCertToNSS(newroot_.get());
82 AddCertToNSS(newrootrollover_.get()); 83 AddCertToNSS(newrootrollover_.get());
84
85 // Check that the certificates can be retrieved as expected.
86 EXPECT_TRUE(
87 TrustStoreContains(target_, {newintermediate_, oldintermediate_}));
88
89 EXPECT_TRUE(TrustStoreContains(newintermediate_,
90 {newroot_, newrootrollover_, oldroot_}));
91 EXPECT_TRUE(TrustStoreContains(oldintermediate_,
92 {newroot_, newrootrollover_, oldroot_}));
93 EXPECT_TRUE(TrustStoreContains(newrootrollover_,
94 {newroot_, newrootrollover_, oldroot_}));
95 EXPECT_TRUE(
96 TrustStoreContains(oldroot_, {newroot_, newrootrollover_, oldroot_}));
97 EXPECT_TRUE(
98 TrustStoreContains(newroot_, {newroot_, newrootrollover_, oldroot_}));
83 } 99 }
84 100
85 // Trusts |cert|. Assumes the cert was already imported into NSS. 101 // Trusts |cert|. Assumes the cert was already imported into NSS.
86 void TrustCert(const TrustAnchor* anchor) { TrustCert(anchor->cert().get()); }
87 void TrustCert(const ParsedCertificate* cert) { 102 void TrustCert(const ParsedCertificate* cert) {
88 SECItem der_cert; 103 SECItem der_cert;
89 der_cert.data = const_cast<uint8_t*>(cert->der_cert().UnsafeData()); 104 der_cert.data = const_cast<uint8_t*>(cert->der_cert().UnsafeData());
90 der_cert.len = base::checked_cast<unsigned>(cert->der_cert().Length()); 105 der_cert.len = base::checked_cast<unsigned>(cert->der_cert().Length());
91 der_cert.type = siDERCertBuffer; 106 der_cert.type = siDERCertBuffer;
92 107
93 ScopedCERTCertificate nss_cert( 108 ScopedCERTCertificate nss_cert(
94 CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert)); 109 CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
95 ASSERT_TRUE(nss_cert); 110 ASSERT_TRUE(nss_cert);
96 111
97 CERTCertTrust trust = {0}; 112 CERTCertTrust trust = {0};
98 trust.sslFlags = 113 trust.sslFlags =
99 CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA | CERTDB_VALID_CA; 114 CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA | CERTDB_VALID_CA;
100 SECStatus srv = 115 SECStatus srv =
101 CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nss_cert.get(), &trust); 116 CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nss_cert.get(), &trust);
102 ASSERT_EQ(SECSuccess, srv); 117 ASSERT_EQ(SECSuccess, srv);
103 } 118 }
104 119
105 protected: 120 protected:
106 bool TrustStoreContains(scoped_refptr<ParsedCertificate> cert, 121 bool TrustStoreContains(scoped_refptr<ParsedCertificate> cert,
107 TrustAnchors expected_matches) { 122 ParsedCertificateList expected_matches) {
108 TrustAnchors matches; 123 ParsedCertificateList matches;
109 trust_store_nss_->FindTrustAnchorsForCert(cert, &matches); 124 trust_store_nss_->SyncGetIssuersOf(cert.get(), &matches);
110 125
111 std::vector<der::Input> der_result_matches; 126 std::vector<std::string> name_result_matches;
112 for (const auto& it : matches) 127 for (const auto& it : matches)
113 der_result_matches.push_back(it->cert()->der_cert()); 128 name_result_matches.push_back(GetCertString(it));
114 std::sort(der_result_matches.begin(), der_result_matches.end()); 129 std::sort(name_result_matches.begin(), name_result_matches.end());
115 130
116 std::vector<der::Input> der_expected_matches; 131 std::vector<std::string> name_expected_matches;
117 for (const auto& it : expected_matches) 132 for (const auto& it : expected_matches)
118 der_expected_matches.push_back(it->cert()->der_cert()); 133 name_expected_matches.push_back(GetCertString(it));
119 std::sort(der_expected_matches.begin(), der_expected_matches.end()); 134 std::sort(name_expected_matches.begin(), name_expected_matches.end());
120 135
121 if (der_expected_matches == der_result_matches) 136 if (name_expected_matches == name_result_matches)
122 return true; 137 return true;
123 138
124 // Print some extra information for debugging. 139 // Print some extra information for debugging.
125 EXPECT_EQ(der_expected_matches, der_result_matches); 140 EXPECT_EQ(name_expected_matches, name_result_matches);
126 return false; 141 return false;
127 } 142 }
128 143
129 scoped_refptr<TrustAnchor> oldroot_; 144 // Give simpler names to certificate DER (for identifying them in tests by
130 scoped_refptr<TrustAnchor> newroot_; 145 // their symbolic name).
146 std::string GetCertString(
147 const scoped_refptr<ParsedCertificate>& cert) const {
148 if (cert->der_cert() == oldroot_->der_cert())
149 return "oldroot_";
150 if (cert->der_cert() == newroot_->der_cert())
151 return "newroot_";
152 if (cert->der_cert() == target_->der_cert())
153 return "target_";
154 if (cert->der_cert() == oldintermediate_->der_cert())
155 return "oldintermediate_";
156 if (cert->der_cert() == newintermediate_->der_cert())
157 return "newintermediate_";
158 if (cert->der_cert() == newrootrollover_->der_cert())
159 return "newrootrollover_";
160 return cert->der_cert().AsString();
161 }
162
163 bool HasTrust(const ParsedCertificateList& certs,
164 CertificateTrustType expected_trust) {
165 bool success = true;
166 for (const scoped_refptr<ParsedCertificate>& cert : certs) {
167 CertificateTrust trust;
168 trust_store_nss_->GetTrust(cert.get(), &trust);
169 if (trust.type != expected_trust) {
170 EXPECT_EQ(expected_trust, trust.type) << GetCertString(cert);
171 success = false;
172 }
173 }
174
175 return success;
176 }
177
178 scoped_refptr<ParsedCertificate> oldroot_;
179 scoped_refptr<ParsedCertificate> newroot_;
131 180
132 scoped_refptr<ParsedCertificate> target_; 181 scoped_refptr<ParsedCertificate> target_;
133 scoped_refptr<ParsedCertificate> oldintermediate_; 182 scoped_refptr<ParsedCertificate> oldintermediate_;
134 scoped_refptr<ParsedCertificate> newintermediate_; 183 scoped_refptr<ParsedCertificate> newintermediate_;
135 scoped_refptr<ParsedCertificate> newrootrollover_; 184 scoped_refptr<ParsedCertificate> newrootrollover_;
136 crypto::ScopedTestNSSDB test_nssdb_; 185 crypto::ScopedTestNSSDB test_nssdb_;
137 std::unique_ptr<TrustStoreNSS> trust_store_nss_; 186 std::unique_ptr<TrustStoreNSS> trust_store_nss_;
138 unsigned nickname_counter_ = 0; 187 unsigned nickname_counter_ = 0;
139 }; 188 };
140 189
141 // Without adding any certs to the NSS DB, should get no anchor results for any 190 // Without adding any certs to the NSS DB, should get no anchor results for any
142 // of the test certs. 191 // of the test certs.
143 TEST_F(TrustStoreNSSTest, CertsNotPresent) { 192 TEST_F(TrustStoreNSSTest, CertsNotPresent) {
144 EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors())); 193 EXPECT_TRUE(TrustStoreContains(target_, ParsedCertificateList()));
145 EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors())); 194 EXPECT_TRUE(TrustStoreContains(newintermediate_, ParsedCertificateList()));
146 EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors())); 195 EXPECT_TRUE(TrustStoreContains(newroot_, ParsedCertificateList()));
147 } 196 }
148 197
149 // If certs are present in NSS DB but aren't marked as trusted, should get no 198 // If certs are present in NSS DB but aren't marked as trusted, should get no
150 // anchor results for any of the test certs. 199 // anchor results for any of the test certs.
151 TEST_F(TrustStoreNSSTest, CertsPresentButNotTrusted) { 200 TEST_F(TrustStoreNSSTest, CertsPresentButNotTrusted) {
152 AddCertsToNSS(); 201 AddCertsToNSS();
153 EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors())); 202
154 EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors())); 203 // None of the certificates are trusted.
155 EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors())); 204 EXPECT_TRUE(HasTrust({oldroot_, newroot_, target_, oldintermediate_,
156 EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors())); 205 newintermediate_, newrootrollover_},
206 CertificateTrustType::UNSPECIFIED));
157 } 207 }
158 208
159 // A self-signed CA certificate is trusted. FindTrustAnchorsForCert should 209 // Trust a single self-signed CA certificate.
160 // return the cert on any intermediates with a matching issuer, and on any
161 // matching self-signed/self-issued CA certs.
162 TEST_F(TrustStoreNSSTest, TrustedCA) { 210 TEST_F(TrustStoreNSSTest, TrustedCA) {
163 AddCertsToNSS(); 211 AddCertsToNSS();
164 TrustCert(newroot_.get()); 212 TrustCert(newroot_.get());
165 EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors())); 213
166 EXPECT_TRUE(TrustStoreContains(newintermediate_, {newroot_})); 214 // Only one of the certificates are trusted.
167 EXPECT_TRUE(TrustStoreContains(oldintermediate_, {newroot_})); 215 EXPECT_TRUE(HasTrust(
168 EXPECT_TRUE(TrustStoreContains(newrootrollover_, {newroot_})); 216 {oldroot_, target_, oldintermediate_, newintermediate_, newrootrollover_},
169 EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), {newroot_})); 217 CertificateTrustType::UNSPECIFIED));
170 EXPECT_TRUE(TrustStoreContains(newroot_->cert(), {newroot_})); 218
219 EXPECT_TRUE(HasTrust({newroot_}, CertificateTrustType::TRUSTED_ANCHOR));
171 } 220 }
172 221
173 // When an intermediate certificate is trusted, FindTrustAnchorsForCert should 222 // Trust a single intermediate certificate.
174 // return that cert on any certs issued by the intermediate, but not for the
175 // intermediate itself (or the CAs).
176 TEST_F(TrustStoreNSSTest, TrustedIntermediate) { 223 TEST_F(TrustStoreNSSTest, TrustedIntermediate) {
177 AddCertsToNSS(); 224 AddCertsToNSS();
178 TrustCert(newintermediate_.get()); 225 TrustCert(newintermediate_.get());
179 EXPECT_TRUE(TrustStoreContains( 226
180 target_, 227 EXPECT_TRUE(HasTrust(
181 {TrustAnchor::CreateFromCertificateNoConstraints(newintermediate_)})); 228 {oldroot_, newroot_, target_, oldintermediate_, newrootrollover_},
182 EXPECT_TRUE(TrustStoreContains(newintermediate_, TrustAnchors())); 229 CertificateTrustType::UNSPECIFIED));
183 EXPECT_TRUE(TrustStoreContains(oldintermediate_, TrustAnchors())); 230 EXPECT_TRUE(
184 EXPECT_TRUE(TrustStoreContains(newrootrollover_, TrustAnchors())); 231 HasTrust({newintermediate_}, CertificateTrustType::TRUSTED_ANCHOR));
185 EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), TrustAnchors()));
186 EXPECT_TRUE(TrustStoreContains(newroot_->cert(), TrustAnchors()));
187 } 232 }
188 233
189 // Multiple self-signed CA certificates with the same name are trusted. 234 // Trust multiple self-signed CA certificates with the same name.
190 // FindTrustAnchorsForCert should return all these certs on any intermediates
191 // with a matching issuer, and on any matching self-signed/self-issued CA certs.
192 TEST_F(TrustStoreNSSTest, MultipleTrustedCAWithSameSubject) { 235 TEST_F(TrustStoreNSSTest, MultipleTrustedCAWithSameSubject) {
193 AddCertsToNSS(); 236 AddCertsToNSS();
194 TrustCert(oldroot_.get()); 237 TrustCert(oldroot_.get());
195 TrustCert(newroot_.get()); 238 TrustCert(newroot_.get());
196 EXPECT_TRUE(TrustStoreContains(target_, TrustAnchors())); 239
197 EXPECT_TRUE(TrustStoreContains(newintermediate_, {newroot_, oldroot_})); 240 EXPECT_TRUE(
198 EXPECT_TRUE(TrustStoreContains(oldintermediate_, {newroot_, oldroot_})); 241 HasTrust({target_, oldintermediate_, newintermediate_, newrootrollover_},
199 EXPECT_TRUE(TrustStoreContains(oldroot_->cert(), {newroot_, oldroot_})); 242 CertificateTrustType::UNSPECIFIED));
243 EXPECT_TRUE(
244 HasTrust({oldroot_, newroot_}, CertificateTrustType::TRUSTED_ANCHOR));
200 } 245 }
201 246
247 class TrustStoreNSSTestDelegate {
248 public:
249 TrustStoreNSSTestDelegate() : trust_store_nss_(trustSSL) {}
250
251 void AddCert(scoped_refptr<ParsedCertificate> cert) {
252 ASSERT_TRUE(test_nssdb_.is_open());
253 std::string nickname = GetUniqueNickname();
254 ScopedCERTCertificate nss_cert(
255 X509Certificate::CreateOSCertHandleFromBytesWithNickname(
256 cert->der_cert().AsStringPiece().data(), cert->der_cert().Length(),
257 nickname.c_str()));
258 ASSERT_TRUE(nss_cert);
259 SECStatus srv =
260 PK11_ImportCert(test_nssdb_.slot(), nss_cert.get(), CK_INVALID_HANDLE,
261 nickname.c_str(), PR_FALSE /* includeTrust (unused) */);
262 ASSERT_EQ(SECSuccess, srv);
263 }
264
265 CertIssuerSource& source() { return trust_store_nss_; }
266
267 protected:
268 std::string GetUniqueNickname() {
269 return "cert_issuer_source_nss_unittest" +
270 base::UintToString(nickname_counter_++);
271 }
272
273 crypto::ScopedTestNSSDB test_nssdb_;
274 TrustStoreNSS trust_store_nss_;
275 unsigned int nickname_counter_ = 0;
276 };
277
278 INSTANTIATE_TYPED_TEST_CASE_P(TrustStoreNSSTest2,
279 CertIssuerSourceSyncTest,
280 TrustStoreNSSTestDelegate);
281
282 // NSS doesn't normalize UTF8String values, so use the not-normalized version of
283 // those tests.
284 INSTANTIATE_TYPED_TEST_CASE_P(TrustStoreNSSNotNormalizedTest,
285 CertIssuerSourceSyncNotNormalizedTest,
286 TrustStoreNSSTestDelegate);
287
202 } // namespace 288 } // namespace
203 289
204 } // namespace net 290 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698