xref: /aosp_15_r20/external/openscreen/cast/test/make_crl_tests.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include <fcntl.h>
6*3f982cf4SFabien Sanglard #include <unistd.h>
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include "cast/common/certificate/cast_crl.h"
9*3f982cf4SFabien Sanglard #include "cast/common/certificate/testing/test_helpers.h"
10*3f982cf4SFabien Sanglard #include "cast/common/certificate/types.h"
11*3f982cf4SFabien Sanglard #include "platform/test/paths.h"
12*3f982cf4SFabien Sanglard #include "util/crypto/certificate_utils.h"
13*3f982cf4SFabien Sanglard #include "util/crypto/digest_sign.h"
14*3f982cf4SFabien Sanglard #include "util/crypto/pem_helpers.h"
15*3f982cf4SFabien Sanglard #include "util/crypto/sha2.h"
16*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
17*3f982cf4SFabien Sanglard 
18*3f982cf4SFabien Sanglard namespace openscreen {
19*3f982cf4SFabien Sanglard namespace cast {
20*3f982cf4SFabien Sanglard namespace {
21*3f982cf4SFabien Sanglard 
AddRevokedPublicKeyHash(TbsCrl * tbs_crl,X509 * cert)22*3f982cf4SFabien Sanglard std::string* AddRevokedPublicKeyHash(TbsCrl* tbs_crl, X509* cert) {
23*3f982cf4SFabien Sanglard   std::string* pubkey_hash = tbs_crl->add_revoked_public_key_hashes();
24*3f982cf4SFabien Sanglard   std::string pubkey_spki = GetSpkiTlv(cert);
25*3f982cf4SFabien Sanglard   *pubkey_hash = SHA256HashString(pubkey_spki).value();
26*3f982cf4SFabien Sanglard   return pubkey_hash;
27*3f982cf4SFabien Sanglard }
28*3f982cf4SFabien Sanglard 
AddSerialNumberRange(TbsCrl * tbs_crl,X509 * issuer,uint64_t first,uint64_t last)29*3f982cf4SFabien Sanglard void AddSerialNumberRange(TbsCrl* tbs_crl,
30*3f982cf4SFabien Sanglard                           X509* issuer,
31*3f982cf4SFabien Sanglard                           uint64_t first,
32*3f982cf4SFabien Sanglard                           uint64_t last) {
33*3f982cf4SFabien Sanglard   SerialNumberRange* serial_range = tbs_crl->add_revoked_serial_number_ranges();
34*3f982cf4SFabien Sanglard   std::string issuer_spki = GetSpkiTlv(issuer);
35*3f982cf4SFabien Sanglard   serial_range->set_issuer_public_key_hash(
36*3f982cf4SFabien Sanglard       SHA256HashString(issuer_spki).value());
37*3f982cf4SFabien Sanglard   serial_range->set_first_serial_number(first);
38*3f982cf4SFabien Sanglard   serial_range->set_last_serial_number(last);
39*3f982cf4SFabien Sanglard }
40*3f982cf4SFabien Sanglard 
MakeTbsCrl(uint64_t not_before,uint64_t not_after,X509 * device_cert,X509 * inter_cert)41*3f982cf4SFabien Sanglard TbsCrl MakeTbsCrl(uint64_t not_before,
42*3f982cf4SFabien Sanglard                   uint64_t not_after,
43*3f982cf4SFabien Sanglard                   X509* device_cert,
44*3f982cf4SFabien Sanglard                   X509* inter_cert) {
45*3f982cf4SFabien Sanglard   TbsCrl tbs_crl;
46*3f982cf4SFabien Sanglard   tbs_crl.set_version(0);
47*3f982cf4SFabien Sanglard   tbs_crl.set_not_before_seconds(not_before);
48*3f982cf4SFabien Sanglard   tbs_crl.set_not_after_seconds(not_after);
49*3f982cf4SFabien Sanglard 
50*3f982cf4SFabien Sanglard   // NOTE: By default, include a hash which should not match any included certs.
51*3f982cf4SFabien Sanglard   std::string* pubkey_hash = AddRevokedPublicKeyHash(&tbs_crl, device_cert);
52*3f982cf4SFabien Sanglard   (*pubkey_hash)[0] ^= 0xff;
53*3f982cf4SFabien Sanglard 
54*3f982cf4SFabien Sanglard   // NOTE: Include default serial number range at device-level, which should not
55*3f982cf4SFabien Sanglard   // include any of our certs.
56*3f982cf4SFabien Sanglard   ErrorOr<uint64_t> maybe_serial =
57*3f982cf4SFabien Sanglard       ParseDerUint64(X509_get0_serialNumber(device_cert));
58*3f982cf4SFabien Sanglard   OSP_DCHECK(maybe_serial);
59*3f982cf4SFabien Sanglard   uint64_t serial = maybe_serial.value();
60*3f982cf4SFabien Sanglard   OSP_DCHECK_LE(serial, UINT64_MAX - 200);
61*3f982cf4SFabien Sanglard   AddSerialNumberRange(&tbs_crl, inter_cert, serial + 100, serial + 200);
62*3f982cf4SFabien Sanglard 
63*3f982cf4SFabien Sanglard   return tbs_crl;
64*3f982cf4SFabien Sanglard }
65*3f982cf4SFabien Sanglard 
66*3f982cf4SFabien Sanglard // Pack into a CrlBundle and sign with |crl_inter_key|.  |crl_inter_der| must be
67*3f982cf4SFabien Sanglard // directly signed by a Cast CRL root CA (possibly distinct from Cast root CA).
PackCrlIntoFile(const std::string & filename,const TbsCrl & tbs_crl,const std::string & crl_inter_der,EVP_PKEY * crl_inter_key)68*3f982cf4SFabien Sanglard void PackCrlIntoFile(const std::string& filename,
69*3f982cf4SFabien Sanglard                      const TbsCrl& tbs_crl,
70*3f982cf4SFabien Sanglard                      const std::string& crl_inter_der,
71*3f982cf4SFabien Sanglard                      EVP_PKEY* crl_inter_key) {
72*3f982cf4SFabien Sanglard   CrlBundle crl_bundle;
73*3f982cf4SFabien Sanglard   Crl* crl = crl_bundle.add_crls();
74*3f982cf4SFabien Sanglard   std::string* tbs_crl_serial = crl->mutable_tbs_crl();
75*3f982cf4SFabien Sanglard   tbs_crl.SerializeToString(tbs_crl_serial);
76*3f982cf4SFabien Sanglard   crl->set_signer_cert(crl_inter_der);
77*3f982cf4SFabien Sanglard   ErrorOr<std::string> signature =
78*3f982cf4SFabien Sanglard       SignData(EVP_sha256(), crl_inter_key,
79*3f982cf4SFabien Sanglard                absl::Span<const uint8_t>{
80*3f982cf4SFabien Sanglard                    reinterpret_cast<const uint8_t*>(tbs_crl_serial->data()),
81*3f982cf4SFabien Sanglard                    tbs_crl_serial->size()});
82*3f982cf4SFabien Sanglard   OSP_DCHECK(signature);
83*3f982cf4SFabien Sanglard   crl->set_signature(std::move(signature.value()));
84*3f982cf4SFabien Sanglard 
85*3f982cf4SFabien Sanglard   std::string output;
86*3f982cf4SFabien Sanglard   crl_bundle.SerializeToString(&output);
87*3f982cf4SFabien Sanglard   int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
88*3f982cf4SFabien Sanglard   OSP_DCHECK_GE(fd, 0);
89*3f982cf4SFabien Sanglard   OSP_DCHECK_EQ(write(fd, output.data(), output.size()),
90*3f982cf4SFabien Sanglard                 static_cast<int>(output.size()));
91*3f982cf4SFabien Sanglard   close(fd);
92*3f982cf4SFabien Sanglard }
93*3f982cf4SFabien Sanglard 
CastMain()94*3f982cf4SFabien Sanglard int CastMain() {
95*3f982cf4SFabien Sanglard   const std::string data_path = GetTestDataPath() + "cast/receiver/channel/";
96*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> inter_key =
97*3f982cf4SFabien Sanglard       ReadKeyFromPemFile(data_path + "inter_key.pem");
98*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> crl_inter_key =
99*3f982cf4SFabien Sanglard       ReadKeyFromPemFile(data_path + "crl_inter_key.pem");
100*3f982cf4SFabien Sanglard   OSP_DCHECK(inter_key);
101*3f982cf4SFabien Sanglard   OSP_DCHECK(crl_inter_key);
102*3f982cf4SFabien Sanglard 
103*3f982cf4SFabien Sanglard   std::vector<std::string> chain_der =
104*3f982cf4SFabien Sanglard       ReadCertificatesFromPemFile(data_path + "device_chain.pem");
105*3f982cf4SFabien Sanglard   std::vector<std::string> crl_inter_der =
106*3f982cf4SFabien Sanglard       ReadCertificatesFromPemFile(data_path + "crl_inter.pem");
107*3f982cf4SFabien Sanglard   OSP_DCHECK_EQ(chain_der.size(), 3u);
108*3f982cf4SFabien Sanglard   OSP_DCHECK_EQ(crl_inter_der.size(), 1u);
109*3f982cf4SFabien Sanglard 
110*3f982cf4SFabien Sanglard   std::string& device_der = chain_der[0];
111*3f982cf4SFabien Sanglard   std::string& inter_der = chain_der[1];
112*3f982cf4SFabien Sanglard   std::string& root_der = chain_der[2];
113*3f982cf4SFabien Sanglard 
114*3f982cf4SFabien Sanglard   auto* data = reinterpret_cast<const uint8_t*>(device_der.data());
115*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> device_cert{
116*3f982cf4SFabien Sanglard       d2i_X509(nullptr, &data, device_der.size())};
117*3f982cf4SFabien Sanglard   data = reinterpret_cast<const uint8_t*>(inter_der.data());
118*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> inter_cert{d2i_X509(nullptr, &data, inter_der.size())};
119*3f982cf4SFabien Sanglard   data = reinterpret_cast<const uint8_t*>(root_der.data());
120*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> root_cert{d2i_X509(nullptr, &data, root_der.size())};
121*3f982cf4SFabien Sanglard   data = reinterpret_cast<const uint8_t*>(crl_inter_der[0].data());
122*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> crl_inter_cert{
123*3f982cf4SFabien Sanglard       d2i_X509(nullptr, &data, crl_inter_der[0].size())};
124*3f982cf4SFabien Sanglard   OSP_DCHECK(device_cert);
125*3f982cf4SFabien Sanglard   OSP_DCHECK(inter_cert);
126*3f982cf4SFabien Sanglard   OSP_DCHECK(root_cert);
127*3f982cf4SFabien Sanglard   OSP_DCHECK(crl_inter_cert);
128*3f982cf4SFabien Sanglard 
129*3f982cf4SFabien Sanglard   // NOTE: CRL where everything should pass.
130*3f982cf4SFabien Sanglard   DateTime july2019 = {};
131*3f982cf4SFabien Sanglard   july2019.month = 7;
132*3f982cf4SFabien Sanglard   july2019.year = 2019;
133*3f982cf4SFabien Sanglard   july2019.day = 16;
134*3f982cf4SFabien Sanglard   DateTime july2020 = {};
135*3f982cf4SFabien Sanglard   july2020.month = 7;
136*3f982cf4SFabien Sanglard   july2020.year = 2020;
137*3f982cf4SFabien Sanglard   july2020.day = 23;
138*3f982cf4SFabien Sanglard   std::chrono::seconds not_before = DateTimeToSeconds(july2019);
139*3f982cf4SFabien Sanglard   std::chrono::seconds not_after = DateTimeToSeconds(july2020);
140*3f982cf4SFabien Sanglard   TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
141*3f982cf4SFabien Sanglard                               device_cert.get(), inter_cert.get());
142*3f982cf4SFabien Sanglard   PackCrlIntoFile(data_path + "good_crl.pb", tbs_crl, crl_inter_der[0],
143*3f982cf4SFabien Sanglard                   crl_inter_key.get());
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard   // NOTE: CRL used outside its valid time range.
146*3f982cf4SFabien Sanglard   {
147*3f982cf4SFabien Sanglard     DateTime august2019 = {};
148*3f982cf4SFabien Sanglard     august2019.month = 8;
149*3f982cf4SFabien Sanglard     august2019.year = 2019;
150*3f982cf4SFabien Sanglard     august2019.day = 16;
151*3f982cf4SFabien Sanglard     std::chrono::seconds not_after = DateTimeToSeconds(august2019);
152*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
153*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
154*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "invalid_time_crl.pb", tbs_crl,
155*3f982cf4SFabien Sanglard                     crl_inter_der[0], crl_inter_key.get());
156*3f982cf4SFabien Sanglard   }
157*3f982cf4SFabien Sanglard 
158*3f982cf4SFabien Sanglard   // NOTE: Device's issuer revoked.
159*3f982cf4SFabien Sanglard   {
160*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
161*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
162*3f982cf4SFabien Sanglard     AddRevokedPublicKeyHash(&tbs_crl, inter_cert.get());
163*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "issuer_revoked_crl.pb", tbs_crl,
164*3f982cf4SFabien Sanglard                     crl_inter_der[0], crl_inter_key.get());
165*3f982cf4SFabien Sanglard   }
166*3f982cf4SFabien Sanglard 
167*3f982cf4SFabien Sanglard   // NOTE: Device revoked.
168*3f982cf4SFabien Sanglard   {
169*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
170*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
171*3f982cf4SFabien Sanglard     AddRevokedPublicKeyHash(&tbs_crl, device_cert.get());
172*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "device_revoked_crl.pb", tbs_crl,
173*3f982cf4SFabien Sanglard                     crl_inter_der[0], crl_inter_key.get());
174*3f982cf4SFabien Sanglard   }
175*3f982cf4SFabien Sanglard 
176*3f982cf4SFabien Sanglard   // NOTE: Issuer serial revoked.
177*3f982cf4SFabien Sanglard   {
178*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
179*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
180*3f982cf4SFabien Sanglard     ErrorOr<uint64_t> maybe_serial =
181*3f982cf4SFabien Sanglard         ParseDerUint64(X509_get0_serialNumber(inter_cert.get()));
182*3f982cf4SFabien Sanglard     OSP_DCHECK(maybe_serial);
183*3f982cf4SFabien Sanglard     uint64_t serial = maybe_serial.value();
184*3f982cf4SFabien Sanglard     OSP_DCHECK_GE(serial, 10);
185*3f982cf4SFabien Sanglard     OSP_DCHECK_LE(serial, UINT64_MAX - 20);
186*3f982cf4SFabien Sanglard     AddSerialNumberRange(&tbs_crl, root_cert.get(), serial - 10, serial + 20);
187*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "issuer_serial_revoked_crl.pb", tbs_crl,
188*3f982cf4SFabien Sanglard                     crl_inter_der[0], crl_inter_key.get());
189*3f982cf4SFabien Sanglard   }
190*3f982cf4SFabien Sanglard 
191*3f982cf4SFabien Sanglard   // NOTE: Device serial revoked.
192*3f982cf4SFabien Sanglard   {
193*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
194*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
195*3f982cf4SFabien Sanglard     ErrorOr<uint64_t> maybe_serial =
196*3f982cf4SFabien Sanglard         ParseDerUint64(X509_get0_serialNumber(device_cert.get()));
197*3f982cf4SFabien Sanglard     OSP_DCHECK(maybe_serial);
198*3f982cf4SFabien Sanglard     uint64_t serial = maybe_serial.value();
199*3f982cf4SFabien Sanglard     OSP_DCHECK_GE(serial, 10);
200*3f982cf4SFabien Sanglard     OSP_DCHECK_LE(serial, UINT64_MAX - 20);
201*3f982cf4SFabien Sanglard     AddSerialNumberRange(&tbs_crl, inter_cert.get(), serial - 10, serial + 20);
202*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "device_serial_revoked_crl.pb", tbs_crl,
203*3f982cf4SFabien Sanglard                     crl_inter_der[0], crl_inter_key.get());
204*3f982cf4SFabien Sanglard   }
205*3f982cf4SFabien Sanglard 
206*3f982cf4SFabien Sanglard   // NOTE: Bad |signer_cert| used for Crl (not issued by Cast CRL root).
207*3f982cf4SFabien Sanglard   {
208*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
209*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
210*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "bad_signer_cert_crl.pb", tbs_crl, inter_der,
211*3f982cf4SFabien Sanglard                     inter_key.get());
212*3f982cf4SFabien Sanglard   }
213*3f982cf4SFabien Sanglard 
214*3f982cf4SFabien Sanglard   // NOTE: Mismatched key for signature in Crl (just looks like bad signature).
215*3f982cf4SFabien Sanglard   {
216*3f982cf4SFabien Sanglard     TbsCrl tbs_crl = MakeTbsCrl(not_before.count(), not_after.count(),
217*3f982cf4SFabien Sanglard                                 device_cert.get(), inter_cert.get());
218*3f982cf4SFabien Sanglard     PackCrlIntoFile(data_path + "bad_signature_crl.pb", tbs_crl,
219*3f982cf4SFabien Sanglard                     crl_inter_der[0], inter_key.get());
220*3f982cf4SFabien Sanglard   }
221*3f982cf4SFabien Sanglard 
222*3f982cf4SFabien Sanglard   return 0;
223*3f982cf4SFabien Sanglard }
224*3f982cf4SFabien Sanglard 
225*3f982cf4SFabien Sanglard }  // namespace
226*3f982cf4SFabien Sanglard }  // namespace cast
227*3f982cf4SFabien Sanglard }  // namespace openscreen
228*3f982cf4SFabien Sanglard 
main()229*3f982cf4SFabien Sanglard int main() {
230*3f982cf4SFabien Sanglard   return openscreen::cast::CastMain();
231*3f982cf4SFabien Sanglard }
232