xref: /openbsd-src/regress/lib/libtls/signer/signertest.c (revision 3da24e266c6277c5c9261103034f973c24e71aa3)
1 /* $OpenBSD: signertest.c,v 1.6 2023/04/14 12:41:26 tb Exp $ */
2 /*
3  * Copyright (c) 2017, 2018, 2022 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 <sys/socket.h>
19 #include <sys/stat.h>
20 
21 #include <err.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include <openssl/bio.h>
29 #include <openssl/err.h>
30 #include <openssl/pem.h>
31 #include <openssl/x509.h>
32 
33 #include <tls.h>
34 
35 #include "tls_internal.h"
36 
37 #ifndef CERTSDIR
38 #define CERTSDIR "."
39 #endif
40 
41 const char *cert_path = CERTSDIR;
42 int sign_cb_count;
43 
44 static void
hexdump(const unsigned char * buf,size_t len)45 hexdump(const unsigned char *buf, size_t len)
46 {
47 	size_t i;
48 
49 	for (i = 1; i <= len; i++)
50 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
51 
52 	fprintf(stderr, "\n");
53 }
54 
55 static void
load_file(const char * filename,const uint8_t ** data,size_t * data_len)56 load_file(const char *filename, const uint8_t **data, size_t *data_len)
57 {
58 	char *filepath;
59 	struct stat sb;
60 	uint8_t *buf;
61 	size_t len;
62 	ssize_t n;
63 	int fd;
64 
65 	if (asprintf(&filepath, "%s/%s", cert_path, filename) == -1)
66 		err(1, "asprintf");
67 	if ((fd = open(filepath, O_RDONLY)) == -1)
68 		err(1, "failed to open '%s'", filepath);
69 	if ((fstat(fd, &sb)) == -1)
70 		err(1, "failed to stat '%s'", filepath);
71 	if (sb.st_size < 0)
72 		err(1, "file size invalid for '%s'", filepath);
73 	len = (size_t)sb.st_size;
74 	if ((buf = malloc(len)) == NULL)
75 		err(1, "out of memory");
76 	n = read(fd, buf, len);
77 	if (n < 0 || (size_t)n != len)
78 		err(1, "failed to read '%s'", filepath);
79 	close(fd);
80 
81 	*data = buf;
82 	*data_len = len;
83 
84 	free(filepath);
85 }
86 
87 static int
compare_mem(char * label,const uint8_t * data1,size_t data1_len,const uint8_t * data2,size_t data2_len)88 compare_mem(char *label, const uint8_t *data1, size_t data1_len,
89     const uint8_t *data2, size_t data2_len)
90 {
91 	if (data1_len != data2_len) {
92 		fprintf(stderr, "FAIL: %s length mismatch (%zu != %zu)\n",
93 		    label, data1_len, data2_len);
94 		fprintf(stderr, "Got:\n");
95 		hexdump(data1, data1_len);
96 		fprintf(stderr, "Want:\n");
97 		hexdump(data2, data2_len);
98 		return -1;
99 	}
100 	if (data1 == data2) {
101 		fprintf(stderr, "FAIL: %s comparing same memory (%p == %p)\n",
102 		    label, data1, data2);
103 		return -1;
104 	}
105 	if (memcmp(data1, data2, data1_len) != 0) {
106 		fprintf(stderr, "FAIL: %s data mismatch\n", label);
107 		fprintf(stderr, "Got:\n");
108 		hexdump(data1, data1_len);
109 		fprintf(stderr, "Want:\n");
110 		hexdump(data2, data2_len);
111 		return -1;
112 	}
113 	return 0;
114 }
115 
116 const char *server_ecdsa_pubkey_hash = \
117     "SHA256:cef2616ece9a57a76d072013b0faad2232511487c67c45bf00fbcecc070e2f5b";
118 const char *server_rsa_pubkey_hash = \
119     "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9f";
120 const char *server_unknown_pubkey_hash = \
121     "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9e";
122 
123 const uint8_t test_digest[] = {
124 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
125 	0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
126 	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
127 	0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
128 };
129 
130 const uint8_t test_rsa_signature[] = {
131 	0x77, 0xfb, 0xdd, 0x41, 0x45, 0x40, 0x25, 0xd6,
132 	0x01, 0xe0, 0x59, 0x04, 0x65, 0xae, 0xa1, 0x59,
133 	0xae, 0xa2, 0x44, 0x08, 0xf7, 0x02, 0x3d, 0xe4,
134 	0xc6, 0x0d, 0x4d, 0x9a, 0x3a, 0xce, 0x34, 0xbe,
135 	0x2e, 0xc0, 0xfc, 0xbd, 0x5b, 0x21, 0xe4, 0xbb,
136 	0xce, 0x02, 0xfd, 0xc3, 0xfc, 0x3d, 0x25, 0xe7,
137 	0xd1, 0x9a, 0x13, 0x60, 0xcb, 0x07, 0xda, 0x23,
138 	0xf7, 0xa3, 0xf0, 0xaf, 0x16, 0x1b, 0x28, 0x54,
139 	0x0a, 0x3c, 0xc1, 0x31, 0x08, 0x0f, 0x2f, 0xce,
140 	0x6d, 0x09, 0x45, 0x48, 0xee, 0x37, 0xa8, 0xc3,
141 	0x91, 0xcb, 0xde, 0xad, 0xc6, 0xcf, 0x18, 0x19,
142 	0xeb, 0xad, 0x08, 0x66, 0x2f, 0xce, 0x1d, 0x07,
143 	0xe3, 0x03, 0x84, 0x00, 0xca, 0x0f, 0x1d, 0x0f,
144 	0x0e, 0x6e, 0x54, 0xc1, 0x39, 0x3f, 0x2a, 0x78,
145 	0xc8, 0xa3, 0x6d, 0x52, 0xb9, 0x26, 0x8e, 0x7e,
146 	0x7a, 0x18, 0x3c, 0x8a, 0x50, 0xa3, 0xad, 0xab,
147 	0xd0, 0x03, 0xc5, 0x3e, 0xa5, 0x46, 0x87, 0xb0,
148 	0x03, 0xde, 0xd9, 0xe5, 0x4d, 0x73, 0x95, 0xcf,
149 	0xe1, 0x59, 0x8e, 0x2e, 0x50, 0x69, 0xe6, 0x20,
150 	0xaf, 0x21, 0x4f, 0xe6, 0xc4, 0x86, 0x11, 0x36,
151 	0x79, 0x68, 0x83, 0xde, 0x0e, 0x81, 0xde, 0x2e,
152 	0xd0, 0x19, 0x3f, 0x4b, 0xad, 0x3e, 0xbf, 0xdd,
153 	0x14, 0x4d, 0x66, 0xf3, 0x7f, 0x7d, 0xca, 0xed,
154 	0x99, 0x62, 0xdc, 0x7c, 0xb2, 0x8b, 0x57, 0xcb,
155 	0xdf, 0xed, 0x16, 0x13, 0x86, 0xd8, 0xd8, 0xb4,
156 	0x44, 0x6e, 0xd5, 0x54, 0xbc, 0xdf, 0xe7, 0x34,
157 	0x10, 0xa4, 0x17, 0x5f, 0xb7, 0xe1, 0x33, 0x2c,
158 	0xc1, 0x70, 0x5b, 0x87, 0x0d, 0x39, 0xee, 0xe8,
159 	0xec, 0x18, 0x92, 0xe8, 0x95, 0xa8, 0x93, 0x26,
160 	0xdf, 0x26, 0x93, 0x96, 0xfd, 0xad, 0x81, 0xb6,
161 	0xeb, 0x72, 0x9c, 0xd4, 0xcc, 0xf6, 0x9f, 0xb0,
162 	0xbb, 0xbd, 0xbd, 0x44, 0x1c, 0x99, 0x07, 0x6d,
163 };
164 
165 static int
do_signer_tests(void)166 do_signer_tests(void)
167 {
168 	char *server_rsa_filepath = NULL;
169 	const uint8_t *server_ecdsa = NULL;
170 	size_t server_ecdsa_len;
171 	struct tls_signer *signer = NULL;
172 	uint8_t *signature = NULL;
173 	size_t signature_len;
174 	EC_KEY *ec_key = NULL;
175 	X509 *x509 = NULL;
176 	BIO *bio = NULL;
177 	int failed = 1;
178 
179 	load_file("server1-ecdsa.pem", &server_ecdsa, &server_ecdsa_len);
180 
181 	if (asprintf(&server_rsa_filepath, "%s/%s", cert_path,
182 	    "server1-rsa.pem") == -1) {
183 		fprintf(stderr, "FAIL: failed to build rsa file path\n");
184 		goto failure;
185 	}
186 
187 	/* Load the ECDSA public key - we'll need it later. */
188 	if ((bio = BIO_new_mem_buf(server_ecdsa, server_ecdsa_len)) == NULL) {
189 		fprintf(stderr, "FAIL: failed to create bio\n");
190 		goto failure;
191 	}
192 	if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) {
193 		fprintf(stderr, "FAIL: failed to load certificate\n");
194 		goto failure;
195 	}
196 	if ((ec_key = EVP_PKEY_get1_EC_KEY(X509_get0_pubkey(x509))) == NULL) {
197 		fprintf(stderr, "FAIL: failed to get EC public key\n");
198 		goto failure;
199 	}
200 
201 	/* Create signer and add key pairs (one ECDSA, one RSA). */
202 	if ((signer = tls_signer_new()) == NULL) {
203 		fprintf(stderr, "FAIL: failed to create tls signer\n");
204 		goto failure;
205 	}
206 	if (tls_signer_add_keypair_mem(signer, server_ecdsa, server_ecdsa_len,
207 	    server_ecdsa, server_ecdsa_len) == -1) {
208 		fprintf(stderr, "FAIL: failed to add ECDSA keypair to tls "
209 		    "signer: %s\n", tls_signer_error(signer));
210 		goto failure;
211 	}
212 	if (tls_signer_add_keypair_file(signer, server_rsa_filepath,
213 	    server_rsa_filepath) == -1) {
214 		fprintf(stderr, "FAIL: failed to add RSA keypair to tls "
215 		    "signer: %s\n", tls_signer_error(signer));
216 		goto failure;
217 	}
218 
219 	/* Sign with RSA. */
220 	if (tls_signer_sign(signer, server_rsa_pubkey_hash, test_digest,
221 	    sizeof(test_digest), TLS_PADDING_RSA_PKCS1, &signature,
222 	    &signature_len) == -1) {
223 		fprintf(stderr, "FAIL: failed to sign with RSA key: %s\n",
224 		    tls_signer_error(signer));
225 		goto failure;
226 	}
227 	if (compare_mem("rsa signature", signature, signature_len,
228 	    test_rsa_signature, sizeof(test_rsa_signature)) == -1)
229 		goto failure;
230 
231 	free(signature);
232 	signature = NULL;
233 
234 	/*
235 	 * Sign with ECDSA - ECDSA signatures are non-deterministic so we cannot
236 	 * check against a known value, rather we can only verify the signature.
237 	 */
238 	if (tls_signer_sign(signer, server_ecdsa_pubkey_hash, test_digest,
239 	    sizeof(test_digest), TLS_PADDING_NONE, &signature,
240 	    &signature_len) == -1) {
241 		fprintf(stderr, "FAIL: failed to sign with ECDSA key: %s\n",
242 		    tls_signer_error(signer));
243 		goto failure;
244 	}
245 	if (ECDSA_verify(0, test_digest, sizeof(test_digest), signature,
246 	    signature_len, ec_key) != 1) {
247 		fprintf(stderr, "FAIL: failed to verify ECDSA signature\n");
248 		goto failure;
249 	}
250 
251 	free(signature);
252 	signature = NULL;
253 
254 	/* Attempt to sign with an unknown cert pubkey hash. */
255 	if (tls_signer_sign(signer, server_unknown_pubkey_hash, test_digest,
256 	    sizeof(test_digest), TLS_PADDING_NONE, &signature,
257 	    &signature_len) != -1) {
258 		fprintf(stderr, "FAIL: signing succeeded with unknown key\n");
259 		goto failure;
260 	}
261 	if (strcmp(tls_signer_error(signer), "key not found") != 0) {
262 		fprintf(stderr, "FAIL: got tls signer error '%s', want "
263 		    "'key not found'\n", tls_signer_error(signer));
264 		goto failure;
265 	}
266 
267 	failed = 0;
268 
269  failure:
270 	BIO_free(bio);
271 	EC_KEY_free(ec_key);
272 	X509_free(x509);
273 	tls_signer_free(signer);
274 	free((uint8_t *)server_ecdsa);
275 	free(server_rsa_filepath);
276 	free(signature);
277 
278 	return failed;
279 }
280 
281 static int
do_tls_handshake(char * name,struct tls * ctx)282 do_tls_handshake(char *name, struct tls *ctx)
283 {
284 	int rv;
285 
286 	rv = tls_handshake(ctx);
287 	if (rv == 0)
288 		return (1);
289 	if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT)
290 		return (0);
291 
292 	errx(1, "%s handshake failed: %s", name, tls_error(ctx));
293 }
294 
295 static int
do_client_server_handshake(char * desc,struct tls * client,struct tls * server_cctx)296 do_client_server_handshake(char *desc, struct tls *client,
297     struct tls *server_cctx)
298 {
299 	int i, client_done, server_done;
300 
301 	i = client_done = server_done = 0;
302 	do {
303 		if (client_done == 0)
304 			client_done = do_tls_handshake("client", client);
305 		if (server_done == 0)
306 			server_done = do_tls_handshake("server", server_cctx);
307 	} while (i++ < 100 && (client_done == 0 || server_done == 0));
308 
309 	if (client_done == 0 || server_done == 0) {
310 		printf("FAIL: %s TLS handshake did not complete\n", desc);
311 		return (1);
312 	}
313 
314 	return (0);
315 }
316 
317 static int
test_tls_handshake_socket(struct tls * client,struct tls * server)318 test_tls_handshake_socket(struct tls *client, struct tls *server)
319 {
320 	struct tls *server_cctx;
321 	int failure;
322 	int sv[2];
323 
324 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC,
325 	    sv) == -1)
326 		err(1, "failed to create socketpair");
327 
328 	if (tls_accept_socket(server, &server_cctx, sv[0]) == -1)
329 		errx(1, "failed to accept: %s", tls_error(server));
330 
331 	if (tls_connect_socket(client, sv[1], "test") == -1)
332 		errx(1, "failed to connect: %s", tls_error(client));
333 
334 	failure = do_client_server_handshake("socket", client, server_cctx);
335 
336 	tls_free(server_cctx);
337 
338 	close(sv[0]);
339 	close(sv[1]);
340 
341 	return (failure);
342 }
343 
344 static int
test_signer_tls_sign(void * cb_arg,const char * pubkey_hash,const uint8_t * input,size_t input_len,int padding_type,uint8_t ** out_signature,size_t * out_signature_len)345 test_signer_tls_sign(void *cb_arg, const char *pubkey_hash,
346     const uint8_t *input, size_t input_len, int padding_type,
347     uint8_t **out_signature, size_t *out_signature_len)
348 {
349 	struct tls_signer *signer = cb_arg;
350 
351 	sign_cb_count++;
352 
353 	return tls_signer_sign(signer, pubkey_hash, input, input_len,
354 	    padding_type, out_signature, out_signature_len);
355 }
356 
357 static int
test_signer_tls(char * certfile,char * keyfile,char * cafile)358 test_signer_tls(char *certfile, char *keyfile, char *cafile)
359 {
360 	struct tls_config *client_cfg, *server_cfg;
361 	struct tls_signer *signer;
362 	struct tls *client, *server;
363 	int failure = 0;
364 
365 	if ((signer = tls_signer_new()) == NULL)
366 		errx(1, "failed to create tls signer");
367 	if (tls_signer_add_keypair_file(signer, certfile, keyfile))
368 		errx(1, "failed to add keypair to signer");
369 
370 	if ((client = tls_client()) == NULL)
371 		errx(1, "failed to create tls client");
372 	if ((client_cfg = tls_config_new()) == NULL)
373 		errx(1, "failed to create tls client config");
374 	tls_config_insecure_noverifyname(client_cfg);
375 	if (tls_config_set_ca_file(client_cfg, cafile) == -1)
376 		errx(1, "failed to set ca: %s", tls_config_error(client_cfg));
377 
378 	if ((server = tls_server()) == NULL)
379 		errx(1, "failed to create tls server");
380 	if ((server_cfg = tls_config_new()) == NULL)
381 		errx(1, "failed to create tls server config");
382 	if (tls_config_set_sign_cb(server_cfg, test_signer_tls_sign,
383 	    signer) == -1)
384 		errx(1, "failed to set server signer callback: %s",
385 		    tls_config_error(server_cfg));
386 	if (tls_config_set_cert_file(server_cfg, certfile) == -1)
387 		errx(1, "failed to set server certificate: %s",
388 		    tls_config_error(server_cfg));
389 
390 	if (tls_configure(client, client_cfg) == -1)
391 		errx(1, "failed to configure client: %s", tls_error(client));
392 	if (tls_configure(server, server_cfg) == -1)
393 		errx(1, "failed to configure server: %s", tls_error(server));
394 
395 	tls_config_free(client_cfg);
396 	tls_config_free(server_cfg);
397 
398 	failure |= test_tls_handshake_socket(client, server);
399 
400 	tls_signer_free(signer);
401 	tls_free(client);
402 	tls_free(server);
403 
404 	return (failure);
405 }
406 
407 static int
do_signer_tls_tests(void)408 do_signer_tls_tests(void)
409 {
410 	char *server_ecdsa_cert = NULL, *server_ecdsa_key = NULL;
411 	char *server_rsa_cert = NULL, *server_rsa_key = NULL;
412 	char *ca_root_ecdsa = NULL, *ca_root_rsa = NULL;
413 	int failure = 0;
414 
415 	if (asprintf(&ca_root_ecdsa, "%s/%s", cert_path,
416 	    "ca-root-ecdsa.pem") == -1)
417 		err(1, "ca ecdsa root");
418 	if (asprintf(&ca_root_rsa, "%s/%s", cert_path,
419 	    "ca-root-rsa.pem") == -1)
420 		err(1, "ca rsa root");
421 	if (asprintf(&server_ecdsa_cert, "%s/%s", cert_path,
422 	    "server1-ecdsa-chain.pem") == -1)
423 		err(1, "server ecdsa chain");
424 	if (asprintf(&server_ecdsa_key, "%s/%s", cert_path,
425 	    "server1-ecdsa.pem") == -1)
426 		err(1, "server ecdsa key");
427 	if (asprintf(&server_rsa_cert, "%s/%s", cert_path,
428 	    "server1-rsa-chain.pem") == -1)
429 		err(1, "server rsa chain");
430 	if (asprintf(&server_rsa_key, "%s/%s", cert_path,
431 	    "server1-rsa.pem") == -1)
432 		err(1, "server rsa key");
433 
434 	failure |= test_signer_tls(server_ecdsa_cert, server_ecdsa_key,
435 	    ca_root_ecdsa);
436 	failure |= test_signer_tls(server_rsa_cert, server_rsa_key,
437 	    ca_root_rsa);
438 
439 	if (sign_cb_count != 2) {
440 		fprintf(stderr, "FAIL: sign callback was called %d times, "
441 		    "want 2\n", sign_cb_count);
442 		failure |= 1;
443 	}
444 
445 	free(ca_root_ecdsa);
446 	free(ca_root_rsa);
447 	free(server_ecdsa_cert);
448 	free(server_ecdsa_key);
449 	free(server_rsa_cert);
450 	free(server_rsa_key);
451 
452 	return (failure);
453 }
454 
455 int
main(int argc,char ** argv)456 main(int argc, char **argv)
457 {
458 	int failure = 0;
459 
460 	if (argc > 2) {
461 		fprintf(stderr, "usage: %s [certpath]\n", argv[0]);
462 		return (1);
463 	}
464 	if (argc == 2)
465 		cert_path = argv[1];
466 
467 	failure |= do_signer_tests();
468 	failure |= do_signer_tls_tests();
469 
470 	return (failure);
471 }
472