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