xref: /aosp_15_r20/external/cronet/net/cert/crl_set_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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/crl_set.h"
6 
7 #include <string_view>
8 
9 #include "base/files/file_util.h"
10 #include "crypto/sha2.h"
11 #include "net/cert/asn1_util.h"
12 #include "net/cert/x509_certificate.h"
13 #include "net/cert/x509_util.h"
14 #include "net/test/cert_test_util.h"
15 #include "net/test/test_data_directory.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace net {
19 
20 // These data blocks were generated using a lot of code that is still in
21 // development. For now, if you need to update them, you have to contact agl.
22 static const uint8_t kGIACRLSet[] = {
23   0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
24   0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
25   0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
26   0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22,
27   0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
28   0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
29   0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
30   0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xb6, 0xb9, 0x54, 0x32, 0xab, 0xae,
31   0x57, 0xfe, 0x02, 0x0c, 0xb2, 0xb7, 0x4f, 0x4f, 0x9f, 0x91, 0x73, 0xc8, 0xc7,
32   0x08, 0xaf, 0xc9, 0xe7, 0x32, 0xac, 0xe2, 0x32, 0x79, 0x04, 0x7c, 0x6d, 0x05,
33   0x0d, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x0d, 0x7f, 0x30, 0x00, 0x03, 0x00, 0x00,
34   0x23, 0xb0, 0x0a, 0x10, 0x0e, 0x37, 0x06, 0x00, 0x03, 0x00, 0x00, 0x23, 0xb1,
35   0x0a, 0x16, 0x25, 0x42, 0x54, 0x00, 0x03, 0x00, 0x00, 0x14, 0x51, 0x0a, 0x16,
36   0x69, 0xd1, 0xd7, 0x00, 0x03, 0x00, 0x00, 0x14, 0x52, 0x0a, 0x16, 0x70, 0x8c,
37   0x22, 0x00, 0x03, 0x00, 0x00, 0x14, 0x53, 0x0a, 0x16, 0x71, 0x31, 0x2c, 0x00,
38   0x03, 0x00, 0x00, 0x14, 0x54, 0x0a, 0x16, 0x7d, 0x75, 0x9d, 0x00, 0x03, 0x00,
39   0x00, 0x14, 0x55, 0x0a, 0x1f, 0xee, 0xf9, 0x49, 0x00, 0x03, 0x00, 0x00, 0x23,
40   0xae, 0x0a, 0x1f, 0xfc, 0xd1, 0x89, 0x00, 0x03, 0x00, 0x00, 0x23, 0xaf, 0x0a,
41   0x61, 0xdd, 0xc7, 0x48, 0x00, 0x03, 0x00, 0x00, 0x18, 0x0e, 0x0a, 0x61, 0xe6,
42   0x12, 0x64, 0x00, 0x03, 0x00, 0x00, 0x18, 0x0f, 0x0a, 0x61, 0xe9, 0x46, 0x56,
43   0x00, 0x03, 0x00, 0x00, 0x18, 0x10, 0x0a, 0x64, 0x63, 0x49, 0xd2, 0x00, 0x03,
44   0x00, 0x00, 0x1d, 0x77,
45 };
46 
47 static const uint8_t kBlockedSPKICRLSet[] = {
48   0x8e, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
49   0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
50   0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
51   0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22,
52   0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
53   0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
54   0x30, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
55   0x49, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x34, 0x37, 0x44, 0x45, 0x51, 0x70, 0x6a,
56   0x38, 0x48, 0x42, 0x53, 0x61, 0x2b, 0x2f, 0x54, 0x49, 0x6d, 0x57, 0x2b, 0x35,
57   0x4a, 0x43, 0x65, 0x75, 0x51, 0x65, 0x52, 0x6b, 0x6d, 0x35, 0x4e, 0x4d, 0x70,
58   0x4a, 0x57, 0x5a, 0x47, 0x33, 0x68, 0x53, 0x75, 0x46, 0x55, 0x3d, 0x22, 0x5d,
59   0x7d,
60 };
61 
62 static const uint8_t kExpiredCRLSet[] = {
63   0x6d, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
64   0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
65   0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
66   0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22,
67   0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
68   0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
69   0x30, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
70   0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x2c, 0x22, 0x4e, 0x6f, 0x74, 0x41, 0x66,
71   0x74, 0x65, 0x72, 0x22, 0x3a, 0x31, 0x7d,
72 };
73 
74 // kGIASPKISHA256 is the SHA256 digest the Google Internet Authority's
75 // SubjectPublicKeyInfo.
76 static const uint8_t kGIASPKISHA256[32] = {
77   0xb6, 0xb9, 0x54, 0x32, 0xab, 0xae, 0x57, 0xfe, 0x02, 0x0c, 0xb2, 0xb7, 0x4f,
78   0x4f, 0x9f, 0x91, 0x73, 0xc8, 0xc7, 0x08, 0xaf, 0xc9, 0xe7, 0x32, 0xac, 0xe2,
79   0x32, 0x79, 0x04, 0x7c, 0x6d, 0x05,
80 };
81 
TEST(CRLSetTest,Parse)82 TEST(CRLSetTest, Parse) {
83   std::string_view s(reinterpret_cast<const char*>(kGIACRLSet),
84                      sizeof(kGIACRLSet));
85   scoped_refptr<CRLSet> set;
86   EXPECT_TRUE(CRLSet::Parse(s, &set));
87   ASSERT_TRUE(set.get() != nullptr);
88 
89   const CRLSet::CRLList& crls = set->CrlsForTesting();
90   ASSERT_EQ(1u, crls.size());
91   const std::vector<std::string>& serials = crls.begin()->second;
92   static const unsigned kExpectedNumSerials = 13;
93   ASSERT_EQ(kExpectedNumSerials, serials.size());
94   EXPECT_EQ(std::string("\x10\x0D\x7F\x30\x00\x03\x00\x00\x23\xB0", 10),
95             serials[0]);
96   EXPECT_EQ(std::string("\x64\x63\x49\xD2\x00\x03\x00\x00\x1D\x77", 10),
97             serials[kExpectedNumSerials - 1]);
98 
99   const std::string gia_spki_hash(reinterpret_cast<const char*>(kGIASPKISHA256),
100                                   sizeof(kGIASPKISHA256));
101   EXPECT_EQ(CRLSet::REVOKED,
102             set->CheckSerial(
103                 std::string("\x16\x7D\x75\x9D\x00\x03\x00\x00\x14\x55", 10),
104                 gia_spki_hash));
105   EXPECT_EQ(CRLSet::GOOD,
106             set->CheckSerial(
107                 std::string("\x47\x54\x3E\x79\x00\x03\x00\x00\x14\xF5", 10),
108                 gia_spki_hash));
109 
110   EXPECT_FALSE(set->IsExpired());
111 }
112 
TEST(CRLSetTest,BlockedSPKIs)113 TEST(CRLSetTest, BlockedSPKIs) {
114   std::string_view s(reinterpret_cast<const char*>(kBlockedSPKICRLSet),
115                      sizeof(kBlockedSPKICRLSet));
116   scoped_refptr<CRLSet> set;
117   EXPECT_TRUE(CRLSet::Parse(s, &set));
118   ASSERT_TRUE(set.get() != nullptr);
119 
120   const uint8_t spki_hash[] = {
121     227, 176, 196, 66, 152, 252, 28, 20, 154, 251, 244, 200, 153, 111, 185, 36,
122     39, 174, 65, 228, 100, 155, 147, 76, 164, 149, 153, 27, 120, 82, 184, 85,
123     0,
124   };
125 
126   EXPECT_EQ(CRLSet::GOOD, set->CheckSPKI(""));
127   EXPECT_EQ(CRLSet::REVOKED,
128             set->CheckSPKI(reinterpret_cast<const char*>(spki_hash)));
129 }
130 
TEST(CertVerifyProcTest,CRLSetIncorporatesStaticBlocklist)131 TEST(CertVerifyProcTest, CRLSetIncorporatesStaticBlocklist) {
132   // Test both the builtin CRLSet and a parsed CRLSet to be sure that both
133   // include the block list.
134   scoped_refptr<CRLSet> set1 = CRLSet::BuiltinCRLSet();
135   ASSERT_TRUE(set1);
136   std::string_view s(reinterpret_cast<const char*>(kGIACRLSet),
137                      sizeof(kGIACRLSet));
138   scoped_refptr<CRLSet> set2;
139   EXPECT_TRUE(CRLSet::Parse(s, &set2));
140   ASSERT_TRUE(set2);
141 
142   static const char* const kDigiNotarFilenames[] = {
143       "diginotar_root_ca.pem",          "diginotar_cyber_ca.pem",
144       "diginotar_services_1024_ca.pem", "diginotar_pkioverheid.pem",
145       "diginotar_pkioverheid_g2.pem",   nullptr,
146   };
147 
148   base::FilePath certs_dir = GetTestCertsDirectory();
149 
150   for (size_t i = 0; kDigiNotarFilenames[i]; i++) {
151     scoped_refptr<X509Certificate> diginotar_cert =
152         ImportCertFromFile(certs_dir, kDigiNotarFilenames[i]);
153     ASSERT_TRUE(diginotar_cert);
154     std::string_view spki;
155     ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(
156         x509_util::CryptoBufferAsStringPiece(diginotar_cert->cert_buffer()),
157         &spki));
158 
159     std::string spki_sha256 = crypto::SHA256HashString(spki);
160 
161     EXPECT_EQ(CRLSet::REVOKED, set1->CheckSPKI(spki_sha256))
162         << "Public key not blocked for " << kDigiNotarFilenames[i];
163     EXPECT_EQ(CRLSet::REVOKED, set2->CheckSPKI(spki_sha256))
164         << "Public key not blocked for " << kDigiNotarFilenames[i];
165   }
166 }
167 
TEST(CRLSetTest,BlockedSubjects)168 TEST(CRLSetTest, BlockedSubjects) {
169   std::string crl_set_bytes;
170   EXPECT_TRUE(base::ReadFileToString(
171       GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
172       &crl_set_bytes));
173   scoped_refptr<CRLSet> set;
174   EXPECT_TRUE(CRLSet::Parse(crl_set_bytes, &set));
175   ASSERT_TRUE(set.get() != nullptr);
176 
177   scoped_refptr<X509Certificate> root = CreateCertificateChainFromFile(
178       GetTestCertsDirectory(), "root_ca_cert.pem",
179       X509Certificate::FORMAT_AUTO);
180   std::string_view root_der =
181       net::x509_util::CryptoBufferAsStringPiece(root->cert_buffer());
182 
183   std::string_view spki;
184   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(root_der, &spki));
185   SHA256HashValue spki_sha256;
186   crypto::SHA256HashString(spki, spki_sha256.data, sizeof(spki_sha256.data));
187 
188   std::string_view subject;
189   ASSERT_TRUE(asn1::ExtractSubjectFromDERCert(root_der, &subject));
190 
191   // Unrelated subjects are unaffected.
192   EXPECT_EQ(CRLSet::GOOD, set->CheckSubject("abcdef", ""));
193 
194   // The subject in question is considered revoked if used with an unknown SPKI
195   // hash.
196   EXPECT_EQ(CRLSet::REVOKED,
197             set->CheckSubject(
198                 subject,
199                 std::string_view(reinterpret_cast<const char*>(kGIASPKISHA256),
200                                  sizeof(kGIASPKISHA256))));
201 
202   // When used with the correct hash, that subject should be accepted.
203   EXPECT_EQ(CRLSet::GOOD,
204             set->CheckSubject(
205                 subject, std::string_view(
206                              reinterpret_cast<const char*>(spki_sha256.data),
207                              sizeof(spki_sha256.data))));
208 }
209 
TEST(CRLSetTest,Expired)210 TEST(CRLSetTest, Expired) {
211   // This CRLSet has an expiry value set to one second past midnight, 1st Jan,
212   // 1970.
213   std::string_view s(reinterpret_cast<const char*>(kExpiredCRLSet),
214                      sizeof(kExpiredCRLSet));
215   scoped_refptr<CRLSet> set;
216   EXPECT_TRUE(CRLSet::Parse(s, &set));
217   ASSERT_TRUE(set.get() != nullptr);
218 
219   EXPECT_TRUE(set->IsExpired());
220 }
221 
222 }  // namespace net
223