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 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 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 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 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 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 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 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 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 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 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 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