1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
6 #define NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
7
8 #include <algorithm>
9
10 #include "net/cert/internal/test_helpers.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/boringssl/src/include/openssl/pool.h"
13 #include "third_party/boringssl/src/pki/cert_errors.h"
14 #include "third_party/boringssl/src/pki/cert_issuer_source.h"
15
16 namespace net {
17
18 namespace {
19
ReadTestPem(const std::string & file_name,const std::string & block_name,std::string * result)20 ::testing::AssertionResult ReadTestPem(const std::string& file_name,
21 const std::string& block_name,
22 std::string* result) {
23 const PemBlockMapping mappings[] = {
24 {block_name.c_str(), result},
25 };
26
27 return ReadTestDataFromPemFile(file_name, mappings);
28 }
29
ReadTestCert(const std::string & file_name,std::shared_ptr<const bssl::ParsedCertificate> * result)30 ::testing::AssertionResult ReadTestCert(
31 const std::string& file_name,
32 std::shared_ptr<const bssl::ParsedCertificate>* result) {
33 std::string der;
34 ::testing::AssertionResult r =
35 ReadTestPem("net/data/cert_issuer_source_static_unittest/" + file_name,
36 "CERTIFICATE", &der);
37 if (!r) {
38 return r;
39 }
40 bssl::CertErrors errors;
41 *result = bssl::ParsedCertificate::Create(
42 bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
43 reinterpret_cast<const uint8_t*>(der.data()), der.size(), nullptr)),
44 {}, &errors);
45 if (!*result) {
46 return ::testing::AssertionFailure()
47 << "ParsedCertificate::Create() failed:\n"
48 << errors.ToDebugString();
49 }
50 return ::testing::AssertionSuccess();
51 }
52
53 } // namespace
54
55 template <typename TestDelegate>
56 class CertIssuerSourceSyncTest : public ::testing::Test {
57 public:
SetUp()58 void SetUp() override {
59 ASSERT_TRUE(ReadTestCert("root.pem", &root_));
60 ASSERT_TRUE(ReadTestCert("i1_1.pem", &i1_1_));
61 ASSERT_TRUE(ReadTestCert("i1_2.pem", &i1_2_));
62 ASSERT_TRUE(ReadTestCert("i2.pem", &i2_));
63 ASSERT_TRUE(ReadTestCert("i3_1.pem", &i3_1_));
64 ASSERT_TRUE(ReadTestCert("i3_2.pem", &i3_2_));
65 ASSERT_TRUE(ReadTestCert("c1.pem", &c1_));
66 ASSERT_TRUE(ReadTestCert("c2.pem", &c2_));
67 ASSERT_TRUE(ReadTestCert("d.pem", &d_));
68 ASSERT_TRUE(ReadTestCert("e1.pem", &e1_));
69 ASSERT_TRUE(ReadTestCert("e2.pem", &e2_));
70 }
71
AddCert(std::shared_ptr<const bssl::ParsedCertificate> cert)72 void AddCert(std::shared_ptr<const bssl::ParsedCertificate> cert) {
73 delegate_.AddCert(std::move(cert));
74 }
75
AddAllCerts()76 void AddAllCerts() {
77 AddCert(root_);
78 AddCert(i1_1_);
79 AddCert(i1_2_);
80 AddCert(i2_);
81 AddCert(i3_1_);
82 AddCert(i3_2_);
83 AddCert(c1_);
84 AddCert(c2_);
85 AddCert(d_);
86 AddCert(e1_);
87 AddCert(e2_);
88 }
89
source()90 bssl::CertIssuerSource& source() { return delegate_.source(); }
91
92 protected:
IssuersMatch(std::shared_ptr<const bssl::ParsedCertificate> cert,bssl::ParsedCertificateList expected_matches)93 bool IssuersMatch(std::shared_ptr<const bssl::ParsedCertificate> cert,
94 bssl::ParsedCertificateList expected_matches) {
95 bssl::ParsedCertificateList matches;
96 source().SyncGetIssuersOf(cert.get(), &matches);
97
98 std::vector<bssl::der::Input> der_result_matches;
99 for (const auto& it : matches) {
100 der_result_matches.push_back(it->der_cert());
101 }
102 std::sort(der_result_matches.begin(), der_result_matches.end());
103
104 std::vector<bssl::der::Input> der_expected_matches;
105 for (const auto& it : expected_matches) {
106 der_expected_matches.push_back(it->der_cert());
107 }
108 std::sort(der_expected_matches.begin(), der_expected_matches.end());
109
110 if (der_expected_matches == der_result_matches) {
111 return true;
112 }
113
114 // Print some extra information for debugging.
115 EXPECT_EQ(der_expected_matches, der_result_matches);
116 return false;
117 }
118
119 TestDelegate delegate_;
120 std::shared_ptr<const bssl::ParsedCertificate> root_;
121 std::shared_ptr<const bssl::ParsedCertificate> i1_1_;
122 std::shared_ptr<const bssl::ParsedCertificate> i1_2_;
123 std::shared_ptr<const bssl::ParsedCertificate> i2_;
124 std::shared_ptr<const bssl::ParsedCertificate> i3_1_;
125 std::shared_ptr<const bssl::ParsedCertificate> i3_2_;
126 std::shared_ptr<const bssl::ParsedCertificate> c1_;
127 std::shared_ptr<const bssl::ParsedCertificate> c2_;
128 std::shared_ptr<const bssl::ParsedCertificate> d_;
129 std::shared_ptr<const bssl::ParsedCertificate> e1_;
130 std::shared_ptr<const bssl::ParsedCertificate> e2_;
131 };
132
133 TYPED_TEST_SUITE_P(CertIssuerSourceSyncTest);
134
TYPED_TEST_P(CertIssuerSourceSyncTest,NoMatch)135 TYPED_TEST_P(CertIssuerSourceSyncTest, NoMatch) {
136 this->AddCert(this->root_);
137
138 EXPECT_TRUE(this->IssuersMatch(this->c1_, {}));
139 }
140
TYPED_TEST_P(CertIssuerSourceSyncTest,OneMatch)141 TYPED_TEST_P(CertIssuerSourceSyncTest, OneMatch) {
142 this->AddAllCerts();
143
144 EXPECT_TRUE(this->IssuersMatch(this->i1_1_, {this->root_}));
145 EXPECT_TRUE(this->IssuersMatch(this->d_, {this->i2_}));
146 }
147
TYPED_TEST_P(CertIssuerSourceSyncTest,MultipleMatches)148 TYPED_TEST_P(CertIssuerSourceSyncTest, MultipleMatches) {
149 this->AddAllCerts();
150
151 EXPECT_TRUE(this->IssuersMatch(this->e1_, {this->i3_1_, this->i3_2_}));
152 EXPECT_TRUE(this->IssuersMatch(this->e2_, {this->i3_1_, this->i3_2_}));
153 }
154
155 // Searching for the issuer of a self-issued cert returns the same cert if it
156 // happens to be in the CertIssuerSourceStatic.
157 // Conceptually this makes sense, though probably not very useful in practice.
158 // Doesn't hurt anything though.
TYPED_TEST_P(CertIssuerSourceSyncTest,SelfIssued)159 TYPED_TEST_P(CertIssuerSourceSyncTest, SelfIssued) {
160 this->AddAllCerts();
161
162 EXPECT_TRUE(this->IssuersMatch(this->root_, {this->root_}));
163 }
164
165 // CertIssuerSourceStatic never returns results asynchronously.
TYPED_TEST_P(CertIssuerSourceSyncTest,IsNotAsync)166 TYPED_TEST_P(CertIssuerSourceSyncTest, IsNotAsync) {
167 this->AddCert(this->i1_1_);
168 std::unique_ptr<bssl::CertIssuerSource::Request> request;
169 this->source().AsyncGetIssuersOf(this->c1_.get(), &request);
170 EXPECT_EQ(nullptr, request);
171 }
172
173 // These are all the tests that should have the same result with or without
174 // normalization.
175 REGISTER_TYPED_TEST_SUITE_P(CertIssuerSourceSyncTest,
176 NoMatch,
177 OneMatch,
178 MultipleMatches,
179 SelfIssued,
180 IsNotAsync);
181
182 template <typename TestDelegate>
183 class CertIssuerSourceSyncNormalizationTest
184 : public CertIssuerSourceSyncTest<TestDelegate> {};
185 TYPED_TEST_SUITE_P(CertIssuerSourceSyncNormalizationTest);
186
TYPED_TEST_P(CertIssuerSourceSyncNormalizationTest,MultipleMatchesAfterNormalization)187 TYPED_TEST_P(CertIssuerSourceSyncNormalizationTest,
188 MultipleMatchesAfterNormalization) {
189 this->AddAllCerts();
190
191 EXPECT_TRUE(this->IssuersMatch(this->c1_, {this->i1_1_, this->i1_2_}));
192 EXPECT_TRUE(this->IssuersMatch(this->c2_, {this->i1_1_, this->i1_2_}));
193 }
194
195 // These tests require (utf8) normalization.
196 REGISTER_TYPED_TEST_SUITE_P(CertIssuerSourceSyncNormalizationTest,
197 MultipleMatchesAfterNormalization);
198
199 template <typename TestDelegate>
200 class CertIssuerSourceSyncNotNormalizedTest
201 : public CertIssuerSourceSyncTest<TestDelegate> {};
202 TYPED_TEST_SUITE_P(CertIssuerSourceSyncNotNormalizedTest);
203
TYPED_TEST_P(CertIssuerSourceSyncNotNormalizedTest,OneMatchWithoutNormalization)204 TYPED_TEST_P(CertIssuerSourceSyncNotNormalizedTest,
205 OneMatchWithoutNormalization) {
206 this->AddAllCerts();
207
208 // Without normalization c1 and c2 should at least be able to find their
209 // exact matching issuer. (c1 should match i1_1, and c2 should match i1_2.)
210 EXPECT_TRUE(this->IssuersMatch(this->c1_, {this->i1_1_}));
211 EXPECT_TRUE(this->IssuersMatch(this->c2_, {this->i1_2_}));
212 }
213
214 // These tests are for implementations which do not do utf8 normalization.
215 REGISTER_TYPED_TEST_SUITE_P(CertIssuerSourceSyncNotNormalizedTest,
216 OneMatchWithoutNormalization);
217
218 } // namespace net
219
220 #endif // NET_CERT_INTERNAL_CERT_ISSUER_SOURCE_SYNC_UNITTEST_H_
221