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