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