1*db8e9f93Stb /* $OpenBSD: cttest.c,v 1.8 2023/04/14 14:36:13 tb Exp $ */
2ef4f8b42Sjsing /*
3ef4f8b42Sjsing * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
4ef4f8b42Sjsing *
5ef4f8b42Sjsing * Permission to use, copy, modify, and distribute this software for any
6ef4f8b42Sjsing * purpose with or without fee is hereby granted, provided that the above
7ef4f8b42Sjsing * copyright notice and this permission notice appear in all copies.
8ef4f8b42Sjsing *
9ef4f8b42Sjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10ef4f8b42Sjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ef4f8b42Sjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12ef4f8b42Sjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ef4f8b42Sjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ef4f8b42Sjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15ef4f8b42Sjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16ef4f8b42Sjsing */
17ef4f8b42Sjsing
18ef4f8b42Sjsing #include <err.h>
19ef4f8b42Sjsing #include <string.h>
20ef4f8b42Sjsing
21e556bfddStb #include <openssl/ct.h>
22ef4f8b42Sjsing #include <openssl/err.h>
23ef4f8b42Sjsing #include <openssl/pem.h>
24ef4f8b42Sjsing #include <openssl/x509v3.h>
25ef4f8b42Sjsing
269fe04e22Stb #ifndef CTPATH
279fe04e22Stb #define CTPATH "."
289fe04e22Stb #endif
299fe04e22Stb
30e060515cSjsing char *test_ctlog_conf_file;
31e060515cSjsing char *test_cert_file;
32e060515cSjsing char *test_issuer_file;
33ef4f8b42Sjsing
34ef4f8b42Sjsing const int debug = 0;
35ef4f8b42Sjsing
36ef4f8b42Sjsing const uint8_t scts_asn1[] = {
37ef4f8b42Sjsing 0x04, 0x81, 0xf2, 0x00, 0xf0, 0x00, 0x77, 0x00,
38ef4f8b42Sjsing 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
39ef4f8b42Sjsing 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
40ef4f8b42Sjsing 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
41ef4f8b42Sjsing 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
42ef4f8b42Sjsing 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x1f, 0x6f,
43ef4f8b42Sjsing 0x00, 0x00, 0x04, 0x03, 0x00, 0x48, 0x30, 0x46,
44ef4f8b42Sjsing 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a, 0x65, 0x98,
45ef4f8b42Sjsing 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26, 0xf7, 0x52,
46ef4f8b42Sjsing 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0, 0x64, 0xcb,
47ef4f8b42Sjsing 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41, 0xe0, 0xbd,
48ef4f8b42Sjsing 0x28, 0x56, 0xad, 0x02, 0x21, 0x00, 0xc2, 0x4f,
49ef4f8b42Sjsing 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55, 0x67, 0x80,
50ef4f8b42Sjsing 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1, 0x96, 0xa7,
51ef4f8b42Sjsing 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c, 0x4e, 0x02,
52ef4f8b42Sjsing 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8, 0x00, 0x75,
53ef4f8b42Sjsing 0x00, 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31,
54ef4f8b42Sjsing 0x19, 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff,
55ef4f8b42Sjsing 0x77, 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00,
56ef4f8b42Sjsing 0x29, 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9,
57ef4f8b42Sjsing 0x13, 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x20,
58ef4f8b42Sjsing 0x3b, 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30,
59ef4f8b42Sjsing 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28, 0x70,
60ef4f8b42Sjsing 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12, 0x1a,
61ef4f8b42Sjsing 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83, 0x36,
62ef4f8b42Sjsing 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40, 0xe1,
63ef4f8b42Sjsing 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae, 0x2b,
64ef4f8b42Sjsing 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb, 0x63,
65ef4f8b42Sjsing 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a, 0x32,
66ef4f8b42Sjsing 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83, 0xa5,
67ef4f8b42Sjsing 0x49, 0x00, 0xc4, 0x57, 0xb8,
68ef4f8b42Sjsing };
69ef4f8b42Sjsing
70c7c0fc11Sjsing const char *sct_log_id1_base64 = "KXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4Q=";
71c7c0fc11Sjsing
72ef4f8b42Sjsing const uint8_t sct_signature1[] = {
73ef4f8b42Sjsing 0x30, 0x46, 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a,
74ef4f8b42Sjsing 0x65, 0x98, 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26,
75ef4f8b42Sjsing 0xf7, 0x52, 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0,
76ef4f8b42Sjsing 0x64, 0xcb, 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41,
77ef4f8b42Sjsing 0xe0, 0xbd, 0x28, 0x56, 0xad, 0x02, 0x21, 0x00,
78ef4f8b42Sjsing 0xc2, 0x4f, 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55,
79ef4f8b42Sjsing 0x67, 0x80, 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1,
80ef4f8b42Sjsing 0x96, 0xa7, 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c,
81ef4f8b42Sjsing 0x4e, 0x02, 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8
82ef4f8b42Sjsing };
83ef4f8b42Sjsing
84c7c0fc11Sjsing const char *sct_signature1_base64 =
85c7c0fc11Sjsing "BAMASDBGAiEAk+06ZZiahfA7PCb3UpTXkkjCwGTLAfXs921B4L0oVq0CIQDCT5L7oLvvVWeABh"
86c7c0fc11Sjsing "AH57mxlqepi7LL05xOAujbJGUeyA==";
87c7c0fc11Sjsing
88c7c0fc11Sjsing const char *sct_log_id2_base64 = "b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM=";
89c7c0fc11Sjsing
90ef4f8b42Sjsing const uint8_t sct_signature2[] = {
91ef4f8b42Sjsing 0x30, 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28,
92ef4f8b42Sjsing 0x70, 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12,
93ef4f8b42Sjsing 0x1a, 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83,
94ef4f8b42Sjsing 0x36, 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40,
95ef4f8b42Sjsing 0xe1, 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae,
96ef4f8b42Sjsing 0x2b, 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb,
97ef4f8b42Sjsing 0x63, 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a,
98ef4f8b42Sjsing 0x32, 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83,
99ef4f8b42Sjsing 0xa5, 0x49, 0x00, 0xc4, 0x57, 0xb8
100ef4f8b42Sjsing };
101ef4f8b42Sjsing
102c7c0fc11Sjsing const char *sct_signature2_base64 =
103c7c0fc11Sjsing "BAMARjBEAiAmyRIocC0VBaei6hIa/zk2X5PfgzZf7Qc4uApA4Y25+gIgYa4rhr2OhmUr+2Ph2n"
104c7c0fc11Sjsing "ez88UqMrgjHn76fYOlSQDEV7g=";
105c7c0fc11Sjsing
106ef4f8b42Sjsing struct sct_data {
107ef4f8b42Sjsing uint8_t version;
108ef4f8b42Sjsing uint8_t log_id[32];
109ef4f8b42Sjsing uint64_t timestamp;
110ef4f8b42Sjsing size_t extensions_len;
111ef4f8b42Sjsing int signature_nid;
112ef4f8b42Sjsing const uint8_t *signature;
113ef4f8b42Sjsing size_t signature_len;
114ef4f8b42Sjsing };
115ef4f8b42Sjsing
116ef4f8b42Sjsing const struct sct_data sct_test_data[] = {
117ef4f8b42Sjsing {
118ef4f8b42Sjsing .version = 0,
119ef4f8b42Sjsing .log_id = {
120ef4f8b42Sjsing 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
121ef4f8b42Sjsing 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
122ef4f8b42Sjsing 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
123ef4f8b42Sjsing 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
124ef4f8b42Sjsing },
12567d5775fSmiod .timestamp = 1637344157551LL,
126ef4f8b42Sjsing .extensions_len = 0,
127ef4f8b42Sjsing .signature_nid = NID_ecdsa_with_SHA256,
128ef4f8b42Sjsing .signature = sct_signature1,
129ef4f8b42Sjsing .signature_len = sizeof(sct_signature1),
130ef4f8b42Sjsing },
131ef4f8b42Sjsing {
132ef4f8b42Sjsing .version = 0,
133ef4f8b42Sjsing .log_id = {
134ef4f8b42Sjsing 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31, 0x19,
135ef4f8b42Sjsing 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff, 0x77,
136ef4f8b42Sjsing 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00, 0x29,
137ef4f8b42Sjsing 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9, 0x13
138ef4f8b42Sjsing },
13967d5775fSmiod .timestamp = 1637344157755LL,
140ef4f8b42Sjsing .extensions_len = 0,
141ef4f8b42Sjsing .signature_nid = NID_ecdsa_with_SHA256,
142ef4f8b42Sjsing .signature = sct_signature2,
143ef4f8b42Sjsing .signature_len = sizeof(sct_signature2),
144ef4f8b42Sjsing },
145ef4f8b42Sjsing };
146ef4f8b42Sjsing
147ef4f8b42Sjsing #define N_SCT_TEST_DATA (sizeof(sct_test_data) / sizeof(*sct_test_data))
148ef4f8b42Sjsing
149ef4f8b42Sjsing static void
hexdump(const unsigned char * buf,size_t len)150ef4f8b42Sjsing hexdump(const unsigned char *buf, size_t len)
151ef4f8b42Sjsing {
152ef4f8b42Sjsing size_t i;
153ef4f8b42Sjsing
154ef4f8b42Sjsing for (i = 1; i <= len; i++)
155ef4f8b42Sjsing fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
156ef4f8b42Sjsing
157ef4f8b42Sjsing if (len % 8)
158ef4f8b42Sjsing fprintf(stderr, "\n");
159ef4f8b42Sjsing }
160ef4f8b42Sjsing
161ef4f8b42Sjsing static void
cert_from_file(const char * filename,X509 ** cert)162ef4f8b42Sjsing cert_from_file(const char *filename, X509 **cert)
163ef4f8b42Sjsing {
164ef4f8b42Sjsing BIO *bio = NULL;
165ef4f8b42Sjsing X509 *x;
166ef4f8b42Sjsing
167ef4f8b42Sjsing if ((bio = BIO_new_file(filename, "r")) == NULL) {
168ef4f8b42Sjsing ERR_print_errors_fp(stderr);
169ef4f8b42Sjsing errx(1, "failed to create bio");
170ef4f8b42Sjsing }
171ef4f8b42Sjsing if ((x = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL)
172ef4f8b42Sjsing errx(1, "failed to read PEM");
173ef4f8b42Sjsing
174ef4f8b42Sjsing *cert = x;
175ef4f8b42Sjsing
176ef4f8b42Sjsing BIO_free(bio);
177ef4f8b42Sjsing }
178ef4f8b42Sjsing
179ef4f8b42Sjsing static int
ct_compare_test_scts(STACK_OF (SCT)* scts)180ef4f8b42Sjsing ct_compare_test_scts(STACK_OF(SCT) *scts)
181ef4f8b42Sjsing {
182ef4f8b42Sjsing const struct sct_data *sdt;
183ef4f8b42Sjsing BIO *bio_err = NULL;
184ef4f8b42Sjsing SCT *sct;
185ef4f8b42Sjsing uint8_t *data;
186ef4f8b42Sjsing size_t len;
187ef4f8b42Sjsing int i;
188ef4f8b42Sjsing int ret = 0;
189ef4f8b42Sjsing
190ef4f8b42Sjsing bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
191ef4f8b42Sjsing
192ef4f8b42Sjsing if (sk_SCT_num(scts) != N_SCT_TEST_DATA) {
193ef4f8b42Sjsing fprintf(stderr, "FAIL: got %d SCTS, want %zu\n",
194ef4f8b42Sjsing sk_SCT_num(scts), N_SCT_TEST_DATA);
195ef4f8b42Sjsing goto failure;
196ef4f8b42Sjsing }
197ef4f8b42Sjsing
198ef4f8b42Sjsing for (i = 0; i < sk_SCT_num(scts); i++) {
199ef4f8b42Sjsing sct = sk_SCT_value(scts, i);
200ef4f8b42Sjsing sdt = &sct_test_data[i];
201ef4f8b42Sjsing
202ef4f8b42Sjsing if (debug > 0) {
203ef4f8b42Sjsing SCT_print(sct, bio_err, 0, NULL);
204ef4f8b42Sjsing BIO_printf(bio_err, "\n");
205ef4f8b42Sjsing }
206ef4f8b42Sjsing
207ef4f8b42Sjsing if (SCT_get_version(sct) != sdt->version) {
208ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got version %u, "
209ef4f8b42Sjsing "want %u\n", i, SCT_get_version(sct), sdt->version);
210ef4f8b42Sjsing goto failure;
211ef4f8b42Sjsing }
212ef4f8b42Sjsing len = SCT_get0_log_id(sct, &data);
213ef4f8b42Sjsing if (len != sizeof(sdt->log_id)) {
214ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got version %u, "
215ef4f8b42Sjsing "want %u\n", i, SCT_get_version(sct), sdt->version);
216ef4f8b42Sjsing goto failure;
217ef4f8b42Sjsing }
218ef4f8b42Sjsing if (memcmp(data, sdt->log_id, len) != 0) {
219ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - log ID differs\n", i);
220ef4f8b42Sjsing fprintf(stderr, "Got:\n");
221ef4f8b42Sjsing hexdump(data, len);
222ef4f8b42Sjsing fprintf(stderr, "Want:\n");
223ef4f8b42Sjsing hexdump(sdt->log_id, sizeof(sdt->log_id));
224ef4f8b42Sjsing goto failure;
225ef4f8b42Sjsing }
226ef4f8b42Sjsing if (SCT_get_timestamp(sct) != sdt->timestamp) {
227ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got timestamp %llu, "
2287086b4c1Stb "want %llu\n", i,
2297086b4c1Stb (unsigned long long)SCT_get_timestamp(sct),
2307086b4c1Stb (unsigned long long)sdt->timestamp);
231ef4f8b42Sjsing goto failure;
232ef4f8b42Sjsing }
233ef4f8b42Sjsing if (SCT_get_signature_nid(sct) != sdt->signature_nid) {
234ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got signature_nid %d, "
235ef4f8b42Sjsing "want %d\n", i, SCT_get_signature_nid(sct),
236ef4f8b42Sjsing sdt->signature_nid);
237ef4f8b42Sjsing goto failure;
238ef4f8b42Sjsing }
239ef4f8b42Sjsing len = SCT_get0_extensions(sct, &data);
240ef4f8b42Sjsing if (len != sdt->extensions_len) {
241ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got extensions with "
242ef4f8b42Sjsing "length %zu, want %zu\n", i, len,
243ef4f8b42Sjsing sdt->extensions_len);
244ef4f8b42Sjsing goto failure;
245ef4f8b42Sjsing }
246ef4f8b42Sjsing len = SCT_get0_signature(sct, &data);
247ef4f8b42Sjsing if (len != sdt->signature_len) {
248ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - got signature with "
249ef4f8b42Sjsing "length %zu, want %zu\n", i, len,
250ef4f8b42Sjsing sdt->signature_len);
251ef4f8b42Sjsing goto failure;
252ef4f8b42Sjsing }
253ef4f8b42Sjsing if (memcmp(data, sdt->signature, len) != 0) {
254ef4f8b42Sjsing fprintf(stderr, "FAIL: SCT %d - signature differs\n",
255ef4f8b42Sjsing i);
256ef4f8b42Sjsing fprintf(stderr, "Got:\n");
257ef4f8b42Sjsing hexdump(data, len);
258ef4f8b42Sjsing fprintf(stderr, "Want:\n");
259ef4f8b42Sjsing hexdump(sdt->signature, sdt->signature_len);
260ef4f8b42Sjsing goto failure;
261ef4f8b42Sjsing }
262ef4f8b42Sjsing }
263ef4f8b42Sjsing
264ef4f8b42Sjsing ret = 1;
265ef4f8b42Sjsing
266ef4f8b42Sjsing failure:
267ef4f8b42Sjsing BIO_free(bio_err);
268ef4f8b42Sjsing
269ef4f8b42Sjsing return ret;
270ef4f8b42Sjsing }
271ef4f8b42Sjsing
272ef4f8b42Sjsing static int
ct_cert_test(void)273ef4f8b42Sjsing ct_cert_test(void)
274ef4f8b42Sjsing {
275ef4f8b42Sjsing X509 *cert = NULL;
276ef4f8b42Sjsing X509_EXTENSION *ext;
277ef4f8b42Sjsing STACK_OF(SCT) *scts = NULL;
278ef4f8b42Sjsing int idx;
279ef4f8b42Sjsing int failed = 1;
280ef4f8b42Sjsing
281ef4f8b42Sjsing cert_from_file(test_cert_file, &cert);
282ef4f8b42Sjsing
283ef4f8b42Sjsing if ((idx = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1)) == -1) {
284ef4f8b42Sjsing fprintf(stderr, "FAIL: failed to find SCTs\n");
285ef4f8b42Sjsing goto failure;
286ef4f8b42Sjsing }
287ef4f8b42Sjsing if ((ext = X509_get_ext(cert, idx)) == NULL) {
288ef4f8b42Sjsing fprintf(stderr, "FAIL: failed to get SCT extension\n");
289ef4f8b42Sjsing goto failure;
290ef4f8b42Sjsing }
291ef4f8b42Sjsing if ((scts = X509V3_EXT_d2i(ext)) == NULL) {
292ef4f8b42Sjsing fprintf(stderr, "FAIL: failed to decode SCTs\n");
293ef4f8b42Sjsing ERR_print_errors_fp(stderr);
294ef4f8b42Sjsing goto failure;
295ef4f8b42Sjsing }
296ef4f8b42Sjsing
297ef4f8b42Sjsing if (!ct_compare_test_scts(scts))
298ef4f8b42Sjsing goto failure;
299ef4f8b42Sjsing
300ef4f8b42Sjsing failed = 0;
301ef4f8b42Sjsing
302ef4f8b42Sjsing failure:
303ef4f8b42Sjsing SCT_LIST_free(scts);
304ef4f8b42Sjsing X509_free(cert);
305ef4f8b42Sjsing
306ef4f8b42Sjsing return failed;
307ef4f8b42Sjsing }
308ef4f8b42Sjsing
309ef4f8b42Sjsing static int
ct_sct_test(void)310ef4f8b42Sjsing ct_sct_test(void)
311ef4f8b42Sjsing {
312ef4f8b42Sjsing STACK_OF(SCT) *scts = NULL;
313ef4f8b42Sjsing const uint8_t *p;
314ef4f8b42Sjsing uint8_t *data = NULL;
315ef4f8b42Sjsing int len;
316ef4f8b42Sjsing int failed = 1;
317ef4f8b42Sjsing
318ef4f8b42Sjsing p = scts_asn1;
319ef4f8b42Sjsing if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) {
320ef4f8b42Sjsing fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n");
321ef4f8b42Sjsing ERR_print_errors_fp(stderr);
322ef4f8b42Sjsing goto failure;
323ef4f8b42Sjsing }
324ef4f8b42Sjsing
325ef4f8b42Sjsing if (!ct_compare_test_scts(scts))
326ef4f8b42Sjsing goto failure;
327ef4f8b42Sjsing
328ef4f8b42Sjsing data = NULL;
329ef4f8b42Sjsing if ((len = i2d_SCT_LIST(scts, &data)) <= 0) {
330ef4f8b42Sjsing fprintf(stderr, "FAIL: failed to encode SCTS to ASN.1\n");
331ef4f8b42Sjsing ERR_print_errors_fp(stderr);
332ef4f8b42Sjsing goto failure;
333ef4f8b42Sjsing }
334ef4f8b42Sjsing if (len != sizeof(scts_asn1)) {
335ef4f8b42Sjsing fprintf(stderr, "FAIL: ASN.1 length differs - got %d, want "
336ef4f8b42Sjsing "%zu\n", len, sizeof(scts_asn1));
337ef4f8b42Sjsing goto failure;
338ef4f8b42Sjsing }
339ef4f8b42Sjsing if (memcmp(data, scts_asn1, len) != 0) {
340ef4f8b42Sjsing fprintf(stderr, "FAIL: ASN.1 for SCTS differs\n");
341ef4f8b42Sjsing fprintf(stderr, "Got:\n");
342ef4f8b42Sjsing hexdump(data, len);
343ef4f8b42Sjsing fprintf(stderr, "Want:\n");
344ef4f8b42Sjsing hexdump(scts_asn1, sizeof(scts_asn1));
345ef4f8b42Sjsing goto failure;
346ef4f8b42Sjsing }
347ef4f8b42Sjsing
348ef4f8b42Sjsing failed = 0;
349ef4f8b42Sjsing
350ef4f8b42Sjsing failure:
351ef4f8b42Sjsing SCT_LIST_free(scts);
352ef4f8b42Sjsing free(data);
353ef4f8b42Sjsing
354ef4f8b42Sjsing return failed;
355ef4f8b42Sjsing }
356ef4f8b42Sjsing
357c7c0fc11Sjsing static int
ct_sct_base64_test(void)358c7c0fc11Sjsing ct_sct_base64_test(void)
359c7c0fc11Sjsing {
360c7c0fc11Sjsing SCT *sct1 = NULL, *sct2 = NULL;
361c7c0fc11Sjsing STACK_OF(SCT) *scts = NULL;
362c7c0fc11Sjsing int failed = 1;
363c7c0fc11Sjsing
364c7c0fc11Sjsing if ((sct1 = SCT_new_from_base64(SCT_VERSION_V1, sct_log_id1_base64,
36567d5775fSmiod CT_LOG_ENTRY_TYPE_X509, 1637344157551LL, "",
366c7c0fc11Sjsing sct_signature1_base64)) == NULL) {
367c7c0fc11Sjsing fprintf(stderr, "FAIL: SCT_new_from_base64() failed\n");
368c7c0fc11Sjsing ERR_print_errors_fp(stderr);
369c7c0fc11Sjsing goto failure;
370c7c0fc11Sjsing }
371c7c0fc11Sjsing if ((sct2 = SCT_new_from_base64(SCT_VERSION_V1, sct_log_id2_base64,
37267d5775fSmiod CT_LOG_ENTRY_TYPE_X509, 1637344157755LL, "",
373c7c0fc11Sjsing sct_signature2_base64)) == NULL) {
374c7c0fc11Sjsing fprintf(stderr, "FAIL: SCT_new_from_base64() failed\n");
375c7c0fc11Sjsing ERR_print_errors_fp(stderr);
376c7c0fc11Sjsing goto failure;
377c7c0fc11Sjsing }
378c7c0fc11Sjsing if ((scts = sk_SCT_new_null()) == NULL)
379c7c0fc11Sjsing goto failure;
380c7c0fc11Sjsing if (!sk_SCT_push(scts, sct1))
381c7c0fc11Sjsing goto failure;
382c7c0fc11Sjsing sct1 = NULL;
383c7c0fc11Sjsing if (!sk_SCT_push(scts, sct2))
384c7c0fc11Sjsing goto failure;
385c7c0fc11Sjsing sct2 = NULL;
386c7c0fc11Sjsing
387c7c0fc11Sjsing if (!ct_compare_test_scts(scts))
388c7c0fc11Sjsing goto failure;
389c7c0fc11Sjsing
390c7c0fc11Sjsing failed = 0;
391c7c0fc11Sjsing
392c7c0fc11Sjsing failure:
393c7c0fc11Sjsing SCT_LIST_free(scts);
394c7c0fc11Sjsing SCT_free(sct1);
395c7c0fc11Sjsing SCT_free(sct2);
396c7c0fc11Sjsing
397c7c0fc11Sjsing return failed;
398c7c0fc11Sjsing }
399c7c0fc11Sjsing
400e060515cSjsing static int
ct_sct_verify_test(void)401e060515cSjsing ct_sct_verify_test(void)
402e060515cSjsing {
403e060515cSjsing STACK_OF(SCT) *scts = NULL;
404e060515cSjsing CT_POLICY_EVAL_CTX *ct_policy = NULL;
405e060515cSjsing CTLOG_STORE *ctlog_store = NULL;
406e060515cSjsing X509 *cert = NULL, *issuer = NULL;
407e060515cSjsing const uint8_t *p;
408e060515cSjsing SCT *sct;
409e060515cSjsing int failed = 1;
410e060515cSjsing
411e060515cSjsing cert_from_file(test_cert_file, &cert);
412e060515cSjsing cert_from_file(test_issuer_file, &issuer);
413e060515cSjsing
414e060515cSjsing if ((ctlog_store = CTLOG_STORE_new()) == NULL)
415e060515cSjsing goto failure;
416e060515cSjsing if (!CTLOG_STORE_load_file(ctlog_store, test_ctlog_conf_file))
417e060515cSjsing goto failure;
418e060515cSjsing
419e060515cSjsing if ((ct_policy = CT_POLICY_EVAL_CTX_new()) == NULL)
420e060515cSjsing goto failure;
421e060515cSjsing
422e060515cSjsing CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ct_policy, ctlog_store);
42367d5775fSmiod CT_POLICY_EVAL_CTX_set_time(ct_policy, 1641393117000LL);
424e060515cSjsing
425e060515cSjsing if (!CT_POLICY_EVAL_CTX_set1_cert(ct_policy, cert))
426e060515cSjsing goto failure;
427e060515cSjsing if (!CT_POLICY_EVAL_CTX_set1_issuer(ct_policy, issuer))
428e060515cSjsing goto failure;
429e060515cSjsing
430e060515cSjsing p = scts_asn1;
431e060515cSjsing if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) {
432e060515cSjsing fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n");
433e060515cSjsing ERR_print_errors_fp(stderr);
434e060515cSjsing goto failure;
435e060515cSjsing }
436e060515cSjsing sct = sk_SCT_value(scts, 0);
437e060515cSjsing
438e060515cSjsing if (!SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT))
439e060515cSjsing goto failure;
440e060515cSjsing if (!SCT_validate(sct, ct_policy)) {
441e060515cSjsing fprintf(stderr, "FAIL: SCT_validate failed\n");
442e060515cSjsing ERR_print_errors_fp(stderr);
443e060515cSjsing goto failure;
444e060515cSjsing }
445e060515cSjsing
446e060515cSjsing failed = 0;
447e060515cSjsing
448e060515cSjsing failure:
449e060515cSjsing CT_POLICY_EVAL_CTX_free(ct_policy);
450e060515cSjsing CTLOG_STORE_free(ctlog_store);
451e060515cSjsing X509_free(cert);
452e060515cSjsing X509_free(issuer);
453*db8e9f93Stb SCT_LIST_free(scts);
454e060515cSjsing
455e060515cSjsing return failed;
456e060515cSjsing }
457e060515cSjsing
458ef4f8b42Sjsing int
main(int argc,char ** argv)459ef4f8b42Sjsing main(int argc, char **argv)
460ef4f8b42Sjsing {
4619fe04e22Stb const char *ctpath = CTPATH;
462ef4f8b42Sjsing int failed = 0;
463ef4f8b42Sjsing
4649fe04e22Stb if (argc > 2) {
4659fe04e22Stb fprintf(stderr, "usage %s [ctpath]\n", argv[0]);
466ef4f8b42Sjsing exit(1);
467ef4f8b42Sjsing }
4689fe04e22Stb if (argc == 2)
469e060515cSjsing ctpath = argv[1];
470ef4f8b42Sjsing
471e060515cSjsing if (asprintf(&test_cert_file, "%s/%s", ctpath,
472e060515cSjsing "libressl.org.crt") == -1)
473e060515cSjsing errx(1, "asprintf test_cert_file");
474e060515cSjsing if (asprintf(&test_issuer_file, "%s/%s", ctpath,
475e060515cSjsing "letsencrypt-r3.crt") == -1)
476e060515cSjsing errx(1, "asprintf test_issuer_file");
477e060515cSjsing if (asprintf(&test_ctlog_conf_file, "%s/%s", ctpath,
478e060515cSjsing "ctlog.conf") == -1)
479e060515cSjsing errx(1, "asprintf test_ctlog_conf_file");
480ef4f8b42Sjsing
481ef4f8b42Sjsing failed |= ct_cert_test();
482ef4f8b42Sjsing failed |= ct_sct_test();
483c7c0fc11Sjsing failed |= ct_sct_base64_test();
484e060515cSjsing failed |= ct_sct_verify_test();
485e060515cSjsing
486e060515cSjsing free(test_cert_file);
487e060515cSjsing free(test_issuer_file);
488e060515cSjsing free(test_ctlog_conf_file);
489ef4f8b42Sjsing
490ef4f8b42Sjsing return (failed);
491ef4f8b42Sjsing }
492