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