xref: /openbsd-src/regress/lib/libcrypto/ct/cttest.c (revision db8e9f93c77297dba1e67e80823fca89b5ae4535)
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