summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/ct/cttest.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/ct/cttest.c')
-rw-r--r--src/regress/lib/libcrypto/ct/cttest.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/ct/cttest.c b/src/regress/lib/libcrypto/ct/cttest.c
new file mode 100644
index 0000000000..f4c5237e5a
--- /dev/null
+++ b/src/regress/lib/libcrypto/ct/cttest.c
@@ -0,0 +1,355 @@
1/* $OpenBSD: cttest.c,v 1.1 2021/12/05 13:01:08 jsing Exp $ */
2/*
3 * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <err.h>
19#include <string.h>
20
21#include <openssl/err.h>
22#include <openssl/pem.h>
23#include <openssl/x509v3.h>
24
25#include "ct/ct.h"
26
27const char *test_cert_file;
28
29const int debug = 0;
30
31const uint8_t scts_asn1[] = {
32 0x04, 0x81, 0xf2, 0x00, 0xf0, 0x00, 0x77, 0x00,
33 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
34 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
35 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
36 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
37 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x1f, 0x6f,
38 0x00, 0x00, 0x04, 0x03, 0x00, 0x48, 0x30, 0x46,
39 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a, 0x65, 0x98,
40 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26, 0xf7, 0x52,
41 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0, 0x64, 0xcb,
42 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41, 0xe0, 0xbd,
43 0x28, 0x56, 0xad, 0x02, 0x21, 0x00, 0xc2, 0x4f,
44 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55, 0x67, 0x80,
45 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1, 0x96, 0xa7,
46 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c, 0x4e, 0x02,
47 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8, 0x00, 0x75,
48 0x00, 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31,
49 0x19, 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff,
50 0x77, 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00,
51 0x29, 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9,
52 0x13, 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x20,
53 0x3b, 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30,
54 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28, 0x70,
55 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12, 0x1a,
56 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83, 0x36,
57 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40, 0xe1,
58 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae, 0x2b,
59 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb, 0x63,
60 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a, 0x32,
61 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83, 0xa5,
62 0x49, 0x00, 0xc4, 0x57, 0xb8,
63};
64
65const uint8_t sct_signature1[] = {
66 0x30, 0x46, 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a,
67 0x65, 0x98, 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26,
68 0xf7, 0x52, 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0,
69 0x64, 0xcb, 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41,
70 0xe0, 0xbd, 0x28, 0x56, 0xad, 0x02, 0x21, 0x00,
71 0xc2, 0x4f, 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55,
72 0x67, 0x80, 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1,
73 0x96, 0xa7, 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c,
74 0x4e, 0x02, 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8
75};
76
77const uint8_t sct_signature2[] = {
78 0x30, 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28,
79 0x70, 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12,
80 0x1a, 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83,
81 0x36, 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40,
82 0xe1, 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae,
83 0x2b, 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb,
84 0x63, 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a,
85 0x32, 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83,
86 0xa5, 0x49, 0x00, 0xc4, 0x57, 0xb8
87};
88
89struct sct_data {
90 uint8_t version;
91 uint8_t log_id[32];
92 uint64_t timestamp;
93 size_t extensions_len;
94 int signature_nid;
95 const uint8_t *signature;
96 size_t signature_len;
97};
98
99const struct sct_data sct_test_data[] = {
100 {
101 .version = 0,
102 .log_id = {
103 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21,
104 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5,
105 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9,
106 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84,
107 },
108 .timestamp = 1637344157551,
109 .extensions_len = 0,
110 .signature_nid = NID_ecdsa_with_SHA256,
111 .signature = sct_signature1,
112 .signature_len = sizeof(sct_signature1),
113 },
114 {
115 .version = 0,
116 .log_id = {
117 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31, 0x19,
118 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff, 0x77,
119 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00, 0x29,
120 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9, 0x13
121 },
122 .timestamp = 1637344157755,
123 .extensions_len = 0,
124 .signature_nid = NID_ecdsa_with_SHA256,
125 .signature = sct_signature2,
126 .signature_len = sizeof(sct_signature2),
127 },
128};
129
130#define N_SCT_TEST_DATA (sizeof(sct_test_data) / sizeof(*sct_test_data))
131
132static void
133hexdump(const unsigned char *buf, size_t len)
134{
135 size_t i;
136
137 for (i = 1; i <= len; i++)
138 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
139
140 if (len % 8)
141 fprintf(stderr, "\n");
142}
143
144static void
145cert_from_file(const char *filename, X509 **cert)
146{
147 BIO *bio = NULL;
148 X509 *x;
149
150 if ((bio = BIO_new_file(filename, "r")) == NULL) {
151 ERR_print_errors_fp(stderr);
152 errx(1, "failed to create bio");
153 }
154 if ((x = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL)
155 errx(1, "failed to read PEM");
156
157 *cert = x;
158
159 BIO_free(bio);
160}
161
162static int
163ct_compare_test_scts(STACK_OF(SCT) *scts)
164{
165 const struct sct_data *sdt;
166 BIO *bio_err = NULL;
167 SCT *sct;
168 uint8_t *data;
169 size_t len;
170 int i;
171 int ret = 0;
172
173 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
174
175 if (sk_SCT_num(scts) != N_SCT_TEST_DATA) {
176 fprintf(stderr, "FAIL: got %d SCTS, want %zu\n",
177 sk_SCT_num(scts), N_SCT_TEST_DATA);
178 goto failure;
179 }
180
181 for (i = 0; i < sk_SCT_num(scts); i++) {
182 sct = sk_SCT_value(scts, i);
183 sdt = &sct_test_data[i];
184
185 if (debug > 0) {
186 SCT_print(sct, bio_err, 0, NULL);
187 BIO_printf(bio_err, "\n");
188 }
189
190 if (SCT_get_version(sct) != sdt->version) {
191 fprintf(stderr, "FAIL: SCT %d - got version %u, "
192 "want %u\n", i, SCT_get_version(sct), sdt->version);
193 goto failure;
194 }
195 len = SCT_get0_log_id(sct, &data);
196 if (len != sizeof(sdt->log_id)) {
197 fprintf(stderr, "FAIL: SCT %d - got version %u, "
198 "want %u\n", i, SCT_get_version(sct), sdt->version);
199 goto failure;
200 }
201 if (memcmp(data, sdt->log_id, len) != 0) {
202 fprintf(stderr, "FAIL: SCT %d - log ID differs\n", i);
203 fprintf(stderr, "Got:\n");
204 hexdump(data, len);
205 fprintf(stderr, "Want:\n");
206 hexdump(sdt->log_id, sizeof(sdt->log_id));
207 goto failure;
208 }
209 if (SCT_get_timestamp(sct) != sdt->timestamp) {
210 fprintf(stderr, "FAIL: SCT %d - got timestamp %llu, "
211 "want %llu\n", i, SCT_get_timestamp(sct),
212 sdt->timestamp);
213 goto failure;
214 }
215 if (SCT_get_signature_nid(sct) != sdt->signature_nid) {
216 fprintf(stderr, "FAIL: SCT %d - got signature_nid %d, "
217 "want %d\n", i, SCT_get_signature_nid(sct),
218 sdt->signature_nid);
219 goto failure;
220 }
221 len = SCT_get0_extensions(sct, &data);
222 if (len != sdt->extensions_len) {
223 fprintf(stderr, "FAIL: SCT %d - got extensions with "
224 "length %zu, want %zu\n", i, len,
225 sdt->extensions_len);
226 goto failure;
227 }
228 len = SCT_get0_signature(sct, &data);
229 if (len != sdt->signature_len) {
230 fprintf(stderr, "FAIL: SCT %d - got signature with "
231 "length %zu, want %zu\n", i, len,
232 sdt->signature_len);
233 goto failure;
234 }
235 if (memcmp(data, sdt->signature, len) != 0) {
236 fprintf(stderr, "FAIL: SCT %d - signature differs\n",
237 i);
238 fprintf(stderr, "Got:\n");
239 hexdump(data, len);
240 fprintf(stderr, "Want:\n");
241 hexdump(sdt->signature, sdt->signature_len);
242 goto failure;
243 }
244 }
245
246 ret = 1;
247
248 failure:
249 BIO_free(bio_err);
250
251 return ret;
252}
253
254static int
255ct_cert_test(void)
256{
257 X509 *cert = NULL;
258 X509_EXTENSION *ext;
259 STACK_OF(SCT) *scts = NULL;
260 int idx;
261 int failed = 1;
262
263 cert_from_file(test_cert_file, &cert);
264
265 if ((idx = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1)) == -1) {
266 fprintf(stderr, "FAIL: failed to find SCTs\n");
267 goto failure;
268 }
269 if ((ext = X509_get_ext(cert, idx)) == NULL) {
270 fprintf(stderr, "FAIL: failed to get SCT extension\n");
271 goto failure;
272 }
273 if ((scts = X509V3_EXT_d2i(ext)) == NULL) {
274 fprintf(stderr, "FAIL: failed to decode SCTs\n");
275 ERR_print_errors_fp(stderr);
276 goto failure;
277 }
278
279 if (!ct_compare_test_scts(scts))
280 goto failure;
281
282 failed = 0;
283
284 failure:
285 SCT_LIST_free(scts);
286 X509_free(cert);
287
288 return failed;
289}
290
291static int
292ct_sct_test(void)
293{
294 STACK_OF(SCT) *scts = NULL;
295 const uint8_t *p;
296 uint8_t *data = NULL;
297 int len;
298 int failed = 1;
299
300 p = scts_asn1;
301 if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) {
302 fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n");
303 ERR_print_errors_fp(stderr);
304 goto failure;
305 }
306
307 if (!ct_compare_test_scts(scts))
308 goto failure;
309
310 data = NULL;
311 if ((len = i2d_SCT_LIST(scts, &data)) <= 0) {
312 fprintf(stderr, "FAIL: failed to encode SCTS to ASN.1\n");
313 ERR_print_errors_fp(stderr);
314 goto failure;
315 }
316 if (len != sizeof(scts_asn1)) {
317 fprintf(stderr, "FAIL: ASN.1 length differs - got %d, want "
318 "%zu\n", len, sizeof(scts_asn1));
319 goto failure;
320 }
321 if (memcmp(data, scts_asn1, len) != 0) {
322 fprintf(stderr, "FAIL: ASN.1 for SCTS differs\n");
323 fprintf(stderr, "Got:\n");
324 hexdump(data, len);
325 fprintf(stderr, "Want:\n");
326 hexdump(scts_asn1, sizeof(scts_asn1));
327 goto failure;
328 }
329
330 failed = 0;
331
332 failure:
333 SCT_LIST_free(scts);
334 free(data);
335
336 return failed;
337}
338
339int
340main(int argc, char **argv)
341{
342 int failed = 0;
343
344 if (argc != 2) {
345 fprintf(stderr, "usage: %s certfile\n", argv[0]);
346 exit(1);
347 }
348
349 test_cert_file = argv[1];
350
351 failed |= ct_cert_test();
352 failed |= ct_sct_test();
353
354 return (failed);
355}