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