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