OLD | NEW |
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 |
OLD | NEW |