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 #include "net/cert/internal/cert_issuer_source_aia.h"
6
7 #include <memory>
8
9 #include "base/files/file_util.h"
10 #include "net/cert/internal/test_helpers.h"
11 #include "net/cert/mock_cert_net_fetcher.h"
12 #include "net/cert/x509_certificate.h"
13 #include "net/cert/x509_util.h"
14 #include "net/test/test_data_directory.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/boringssl/src/pki/cert_errors.h"
18 #include "third_party/boringssl/src/pki/parsed_certificate.h"
19 #include "url/gurl.h"
20
21 namespace net {
22
23 namespace {
24
25 using ::testing::ByMove;
26 using ::testing::Mock;
27 using ::testing::Return;
28 using ::testing::StrictMock;
29 using ::testing::_;
30
ReadTestPem(const std::string & file_name,const std::string & block_name,std::string * result)31 ::testing::AssertionResult ReadTestPem(const std::string& file_name,
32 const std::string& block_name,
33 std::string* result) {
34 const PemBlockMapping mappings[] = {
35 {block_name.c_str(), result},
36 };
37
38 return ReadTestDataFromPemFile(file_name, mappings);
39 }
40
ReadTestCert(const std::string & file_name,std::shared_ptr<const bssl::ParsedCertificate> * result)41 ::testing::AssertionResult ReadTestCert(
42 const std::string& file_name,
43 std::shared_ptr<const bssl::ParsedCertificate>* result) {
44 std::string der;
45 ::testing::AssertionResult r =
46 ReadTestPem("net/data/cert_issuer_source_aia_unittest/" + file_name,
47 "CERTIFICATE", &der);
48 if (!r)
49 return r;
50 bssl::CertErrors errors;
51 *result = bssl::ParsedCertificate::Create(x509_util::CreateCryptoBuffer(der),
52 {}, &errors);
53 if (!*result) {
54 return ::testing::AssertionFailure()
55 << "bssl::ParsedCertificate::Create() failed:\n"
56 << errors.ToDebugString();
57 }
58 return ::testing::AssertionSuccess();
59 }
60
61 // CertIssuerSourceAia does not return results for SyncGetIssuersOf.
TEST(CertIssuerSourceAiaTest,NoSyncResults)62 TEST(CertIssuerSourceAiaTest, NoSyncResults) {
63 std::shared_ptr<const bssl::ParsedCertificate> cert;
64 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
65
66 // No methods on |mock_fetcher| should be called.
67 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
68 CertIssuerSourceAia aia_source(mock_fetcher);
69 bssl::ParsedCertificateList issuers;
70 aia_source.SyncGetIssuersOf(cert.get(), &issuers);
71 EXPECT_EQ(0U, issuers.size());
72 }
73
74 // If the AuthorityInfoAccess extension is not present, AsyncGetIssuersOf should
75 // synchronously indicate no results.
TEST(CertIssuerSourceAiaTest,NoAia)76 TEST(CertIssuerSourceAiaTest, NoAia) {
77 std::shared_ptr<const bssl::ParsedCertificate> cert;
78 ASSERT_TRUE(ReadTestCert("target_no_aia.pem", &cert));
79
80 // No methods on |mock_fetcher| should be called.
81 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
82 CertIssuerSourceAia aia_source(mock_fetcher);
83 std::unique_ptr<bssl::CertIssuerSource::Request> request;
84 aia_source.AsyncGetIssuersOf(cert.get(), &request);
85 EXPECT_EQ(nullptr, request);
86 }
87
88 // If the AuthorityInfoAccess extension only contains non-HTTP URIs,
89 // AsyncGetIssuersOf should create a Request object. The URL scheme check is
90 // part of the specific CertNetFetcher implementation, this tests that we handle
91 // ERR_DISALLOWED_URL_SCHEME properly. If FetchCaIssuers is modified to fail
92 // synchronously in that case, this test will be more interesting.
TEST(CertIssuerSourceAiaTest,FileAia)93 TEST(CertIssuerSourceAiaTest, FileAia) {
94 std::shared_ptr<const bssl::ParsedCertificate> cert;
95 ASSERT_TRUE(ReadTestCert("target_file_aia.pem", &cert));
96
97 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
98 EXPECT_CALL(*mock_fetcher, FetchCaIssuers(GURL("file:///dev/null"), _, _))
99 .WillOnce(Return(ByMove(
100 MockCertNetFetcherRequest::Create(ERR_DISALLOWED_URL_SCHEME))));
101
102 CertIssuerSourceAia aia_source(mock_fetcher);
103 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
104 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
105 ASSERT_NE(nullptr, cert_source_request);
106
107 // No results.
108 bssl::ParsedCertificateList result_certs;
109 cert_source_request->GetNext(&result_certs);
110 EXPECT_TRUE(result_certs.empty());
111 }
112
113 // If the AuthorityInfoAccess extension contains an invalid URL,
114 // AsyncGetIssuersOf should synchronously indicate no results.
TEST(CertIssuerSourceAiaTest,OneInvalidURL)115 TEST(CertIssuerSourceAiaTest, OneInvalidURL) {
116 std::shared_ptr<const bssl::ParsedCertificate> cert;
117 ASSERT_TRUE(ReadTestCert("target_invalid_url_aia.pem", &cert));
118
119 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
120 CertIssuerSourceAia aia_source(mock_fetcher);
121 std::unique_ptr<bssl::CertIssuerSource::Request> request;
122 aia_source.AsyncGetIssuersOf(cert.get(), &request);
123 EXPECT_EQ(nullptr, request);
124 }
125
126 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert.
TEST(CertIssuerSourceAiaTest,OneAia)127 TEST(CertIssuerSourceAiaTest, OneAia) {
128 std::shared_ptr<const bssl::ParsedCertificate> cert;
129 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
130 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert;
131 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
132
133 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
134
135 EXPECT_CALL(*mock_fetcher,
136 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
137 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
138 intermediate_cert->cert_buffer()))));
139
140 CertIssuerSourceAia aia_source(mock_fetcher);
141 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
142 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
143 ASSERT_NE(nullptr, cert_source_request);
144
145 bssl::ParsedCertificateList result_certs;
146 cert_source_request->GetNext(&result_certs);
147 ASSERT_EQ(1u, result_certs.size());
148 ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
149
150 result_certs.clear();
151 cert_source_request->GetNext(&result_certs);
152 EXPECT_TRUE(result_certs.empty());
153 }
154
155 // AuthorityInfoAccess with two URIs, one a FILE, the other a HTTP.
156 // Simulate a ERR_DISALLOWED_URL_SCHEME for the file URL. If FetchCaIssuers is
157 // modified to synchronously reject disallowed schemes, this test will be more
158 // interesting.
TEST(CertIssuerSourceAiaTest,OneFileOneHttpAia)159 TEST(CertIssuerSourceAiaTest, OneFileOneHttpAia) {
160 std::shared_ptr<const bssl::ParsedCertificate> cert;
161 ASSERT_TRUE(ReadTestCert("target_file_and_http_aia.pem", &cert));
162 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert;
163 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert));
164
165 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
166
167 EXPECT_CALL(*mock_fetcher, FetchCaIssuers(GURL("file:///dev/null"), _, _))
168 .WillOnce(Return(ByMove(
169 MockCertNetFetcherRequest::Create(ERR_DISALLOWED_URL_SCHEME))));
170
171 EXPECT_CALL(*mock_fetcher,
172 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
173 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
174 intermediate_cert->cert_buffer()))));
175
176 CertIssuerSourceAia aia_source(mock_fetcher);
177 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
178 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
179 ASSERT_NE(nullptr, cert_source_request);
180
181 bssl::ParsedCertificateList result_certs;
182 cert_source_request->GetNext(&result_certs);
183 ASSERT_EQ(1u, result_certs.size());
184 ASSERT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
185
186 cert_source_request->GetNext(&result_certs);
187 EXPECT_EQ(1u, result_certs.size());
188 }
189
190 // AuthorityInfoAccess with two URIs, one is invalid, the other HTTP.
TEST(CertIssuerSourceAiaTest,OneInvalidOneHttpAia)191 TEST(CertIssuerSourceAiaTest, OneInvalidOneHttpAia) {
192 std::shared_ptr<const bssl::ParsedCertificate> cert;
193 ASSERT_TRUE(ReadTestCert("target_invalid_and_http_aia.pem", &cert));
194 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert;
195 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert));
196
197 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
198
199 EXPECT_CALL(*mock_fetcher,
200 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
201 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
202 intermediate_cert->cert_buffer()))));
203
204 CertIssuerSourceAia aia_source(mock_fetcher);
205 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
206 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
207 ASSERT_NE(nullptr, cert_source_request);
208
209 bssl::ParsedCertificateList result_certs;
210 cert_source_request->GetNext(&result_certs);
211 ASSERT_EQ(1u, result_certs.size());
212 EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
213
214 // No more results.
215 result_certs.clear();
216 cert_source_request->GetNext(&result_certs);
217 EXPECT_EQ(0u, result_certs.size());
218 }
219
220 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert.
221 // One request completes, results are retrieved, then the next request completes
222 // and the results are retrieved.
TEST(CertIssuerSourceAiaTest,TwoAiaCompletedInSeries)223 TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeries) {
224 std::shared_ptr<const bssl::ParsedCertificate> cert;
225 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
226 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert;
227 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
228 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert2;
229 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2));
230
231 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
232
233 EXPECT_CALL(*mock_fetcher,
234 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
235 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
236 intermediate_cert->cert_buffer()))));
237
238 EXPECT_CALL(*mock_fetcher,
239 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
240 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
241 intermediate_cert2->cert_buffer()))));
242
243 CertIssuerSourceAia aia_source(mock_fetcher);
244 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
245 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
246 ASSERT_NE(nullptr, cert_source_request);
247
248 // GetNext() should return intermediate_cert followed by intermediate_cert2.
249 // They are returned in two separate batches.
250 bssl::ParsedCertificateList result_certs;
251 cert_source_request->GetNext(&result_certs);
252 ASSERT_EQ(1u, result_certs.size());
253 EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
254
255 result_certs.clear();
256 cert_source_request->GetNext(&result_certs);
257 ASSERT_EQ(1u, result_certs.size());
258 EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert2->der_cert());
259
260 // No more results.
261 result_certs.clear();
262 cert_source_request->GetNext(&result_certs);
263 EXPECT_EQ(0u, result_certs.size());
264 }
265
266 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert,
267 // CertNetFetcher request fails.
TEST(CertIssuerSourceAiaTest,OneAiaHttpError)268 TEST(CertIssuerSourceAiaTest, OneAiaHttpError) {
269 std::shared_ptr<const bssl::ParsedCertificate> cert;
270 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
271
272 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
273
274 // HTTP request returns with an error.
275 EXPECT_CALL(*mock_fetcher,
276 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
277 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(ERR_FAILED))));
278
279 CertIssuerSourceAia aia_source(mock_fetcher);
280 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
281 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
282 ASSERT_NE(nullptr, cert_source_request);
283
284 // No results.
285 bssl::ParsedCertificateList result_certs;
286 cert_source_request->GetNext(&result_certs);
287 ASSERT_EQ(0u, result_certs.size());
288 }
289
290 // AuthorityInfoAccess with a single HTTP url pointing to a single DER cert,
291 // CertNetFetcher request completes, but the DER cert fails to parse.
TEST(CertIssuerSourceAiaTest,OneAiaParseError)292 TEST(CertIssuerSourceAiaTest, OneAiaParseError) {
293 std::shared_ptr<const bssl::ParsedCertificate> cert;
294 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
295
296 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
297
298 // HTTP request returns invalid certificate data.
299 EXPECT_CALL(*mock_fetcher,
300 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
301 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
302 std::vector<uint8_t>({1, 2, 3, 4, 5})))));
303
304 CertIssuerSourceAia aia_source(mock_fetcher);
305 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
306 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
307 ASSERT_NE(nullptr, cert_source_request);
308
309 // No results.
310 bssl::ParsedCertificateList result_certs;
311 cert_source_request->GetNext(&result_certs);
312 ASSERT_EQ(0u, result_certs.size());
313 }
314
315 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert.
316 // One request fails.
TEST(CertIssuerSourceAiaTest,TwoAiaCompletedInSeriesFirstFails)317 TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeriesFirstFails) {
318 std::shared_ptr<const bssl::ParsedCertificate> cert;
319 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
320 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert2;
321 ASSERT_TRUE(ReadTestCert("i2.pem", &intermediate_cert2));
322
323 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
324
325 // Request for I.cer completes first, but fails.
326 EXPECT_CALL(*mock_fetcher,
327 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
328 .WillOnce(Return(
329 ByMove(MockCertNetFetcherRequest::Create(ERR_INVALID_RESPONSE))));
330
331 // Request for I2.foo succeeds.
332 EXPECT_CALL(*mock_fetcher,
333 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
334 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
335 intermediate_cert2->cert_buffer()))));
336
337 CertIssuerSourceAia aia_source(mock_fetcher);
338 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
339 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
340 ASSERT_NE(nullptr, cert_source_request);
341
342 // GetNext() should return intermediate_cert2.
343 bssl::ParsedCertificateList result_certs;
344 cert_source_request->GetNext(&result_certs);
345 ASSERT_EQ(1u, result_certs.size());
346 EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert2->der_cert());
347
348 // No more results.
349 result_certs.clear();
350 cert_source_request->GetNext(&result_certs);
351 EXPECT_EQ(0u, result_certs.size());
352 }
353
354 // AuthorityInfoAccess with two HTTP urls, each pointing to a single DER cert.
355 // First request completes, result is retrieved, then the second request fails.
TEST(CertIssuerSourceAiaTest,TwoAiaCompletedInSeriesSecondFails)356 TEST(CertIssuerSourceAiaTest, TwoAiaCompletedInSeriesSecondFails) {
357 std::shared_ptr<const bssl::ParsedCertificate> cert;
358 ASSERT_TRUE(ReadTestCert("target_two_aia.pem", &cert));
359 std::shared_ptr<const bssl::ParsedCertificate> intermediate_cert;
360 ASSERT_TRUE(ReadTestCert("i.pem", &intermediate_cert));
361
362 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
363
364 // Request for I.cer completes first.
365 EXPECT_CALL(*mock_fetcher,
366 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
367 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
368 intermediate_cert->cert_buffer()))));
369
370 // Request for I2.foo fails.
371 EXPECT_CALL(*mock_fetcher,
372 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
373 .WillOnce(Return(
374 ByMove(MockCertNetFetcherRequest::Create(ERR_INVALID_RESPONSE))));
375
376 CertIssuerSourceAia aia_source(mock_fetcher);
377 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
378 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
379 ASSERT_NE(nullptr, cert_source_request);
380
381 // GetNext() should return intermediate_cert.
382 bssl::ParsedCertificateList result_certs;
383 cert_source_request->GetNext(&result_certs);
384 ASSERT_EQ(1u, result_certs.size());
385 EXPECT_EQ(result_certs.front()->der_cert(), intermediate_cert->der_cert());
386
387 // No more results.
388 result_certs.clear();
389 cert_source_request->GetNext(&result_certs);
390 EXPECT_EQ(0u, result_certs.size());
391 }
392
393 // AuthorityInfoAccess with six HTTP URLs. kMaxFetchesPerCert is 5, so the
394 // sixth URL should be ignored.
TEST(CertIssuerSourceAiaTest,MaxFetchesPerCert)395 TEST(CertIssuerSourceAiaTest, MaxFetchesPerCert) {
396 std::shared_ptr<const bssl::ParsedCertificate> cert;
397 ASSERT_TRUE(ReadTestCert("target_six_aia.pem", &cert));
398
399 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
400
401 std::vector<uint8_t> bad_der({1, 2, 3, 4, 5});
402
403 EXPECT_CALL(*mock_fetcher,
404 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
405 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(bad_der))));
406
407 EXPECT_CALL(*mock_fetcher,
408 FetchCaIssuers(GURL("http://url-for-aia2/I2.foo"), _, _))
409 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(bad_der))));
410
411 EXPECT_CALL(*mock_fetcher,
412 FetchCaIssuers(GURL("http://url-for-aia3/I3.foo"), _, _))
413 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(bad_der))));
414
415 EXPECT_CALL(*mock_fetcher,
416 FetchCaIssuers(GURL("http://url-for-aia4/I4.foo"), _, _))
417 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(bad_der))));
418
419 EXPECT_CALL(*mock_fetcher,
420 FetchCaIssuers(GURL("http://url-for-aia5/I5.foo"), _, _))
421 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(bad_der))));
422
423 // Note that the sixth URL (http://url-for-aia6/I6.foo) will not be requested.
424
425 CertIssuerSourceAia aia_source(mock_fetcher);
426 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
427 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
428 ASSERT_NE(nullptr, cert_source_request);
429
430 // GetNext() will not get any certificates (since the first 5 fail to be
431 // parsed, and the sixth URL is not attempted).
432 bssl::ParsedCertificateList result_certs;
433 cert_source_request->GetNext(&result_certs);
434 ASSERT_EQ(0u, result_certs.size());
435 }
436
437 // AuthorityInfoAccess that returns a certs-only CMS message containing two
438 // certificates.
TEST(CertIssuerSourceAiaTest,CertsOnlyCmsMessage)439 TEST(CertIssuerSourceAiaTest, CertsOnlyCmsMessage) {
440 base::FilePath cert_path =
441 GetTestCertsDirectory().AppendASCII("google.binary.p7b");
442 std::string cert_data;
443 ASSERT_TRUE(base::ReadFileToString(cert_path, &cert_data));
444
445 std::shared_ptr<const bssl::ParsedCertificate> cert;
446 ASSERT_TRUE(ReadTestCert("target_one_aia.pem", &cert));
447
448 auto mock_fetcher = base::MakeRefCounted<StrictMock<MockCertNetFetcher>>();
449
450 EXPECT_CALL(*mock_fetcher,
451 FetchCaIssuers(GURL("http://url-for-aia/I.cer"), _, _))
452 .WillOnce(Return(ByMove(MockCertNetFetcherRequest::Create(
453 std::vector<uint8_t>(cert_data.begin(), cert_data.end())))));
454
455 CertIssuerSourceAia aia_source(mock_fetcher);
456 std::unique_ptr<bssl::CertIssuerSource::Request> cert_source_request;
457 aia_source.AsyncGetIssuersOf(cert.get(), &cert_source_request);
458 ASSERT_NE(nullptr, cert_source_request);
459
460 bssl::ParsedCertificateList result_certs;
461 cert_source_request->GetNext(&result_certs);
462 ASSERT_EQ(2u, result_certs.size());
463
464 // The fingerprint of the Google certificate used in the parsing tests.
465 SHA256HashValue google_parse_fingerprint = {
466 {0xf6, 0x41, 0xc3, 0x6c, 0xfe, 0xf4, 0x9b, 0xc0, 0x71, 0x35, 0x9e,
467 0xcf, 0x88, 0xee, 0xd9, 0x31, 0x7b, 0x73, 0x8b, 0x59, 0x89, 0x41,
468 0x6a, 0xd4, 0x01, 0x72, 0x0c, 0x0a, 0x4e, 0x2e, 0x63, 0x52}};
469 // The fingerprint for the Thawte SGC certificate
470 SHA256HashValue thawte_parse_fingerprint = {
471 {0x10, 0x85, 0xa6, 0xf4, 0x54, 0xd0, 0xc9, 0x11, 0x98, 0xfd, 0xda,
472 0xb1, 0x1a, 0x31, 0xc7, 0x16, 0xd5, 0xdc, 0xd6, 0x8d, 0xf9, 0x1c,
473 0x03, 0x9c, 0xe1, 0x8d, 0xca, 0x9b, 0xeb, 0x3c, 0xde, 0x3d}};
474 EXPECT_EQ(google_parse_fingerprint, X509Certificate::CalculateFingerprint256(
475 result_certs[0]->cert_buffer()));
476 EXPECT_EQ(thawte_parse_fingerprint, X509Certificate::CalculateFingerprint256(
477 result_certs[1]->cert_buffer()));
478 result_certs.clear();
479 cert_source_request->GetNext(&result_certs);
480 EXPECT_TRUE(result_certs.empty());
481 }
482
483 } // namespace
484
485 } // namespace net
486