1*0ba45550Sjsing /* $OpenBSD: keypairtest.c,v 1.7 2024/03/20 10:38:05 jsing Exp $ */
27ad73a06Sjsing /*
37ad73a06Sjsing * Copyright (c) 2018 Joel Sing <jsing@openbsd.org>
47ad73a06Sjsing *
57ad73a06Sjsing * Permission to use, copy, modify, and distribute this software for any
67ad73a06Sjsing * purpose with or without fee is hereby granted, provided that the above
77ad73a06Sjsing * copyright notice and this permission notice appear in all copies.
87ad73a06Sjsing *
97ad73a06Sjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
107ad73a06Sjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
117ad73a06Sjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
127ad73a06Sjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
137ad73a06Sjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
147ad73a06Sjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
157ad73a06Sjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167ad73a06Sjsing */
177ad73a06Sjsing
187ad73a06Sjsing #include <sys/stat.h>
197ad73a06Sjsing
207ad73a06Sjsing #include <err.h>
217ad73a06Sjsing #include <fcntl.h>
227ad73a06Sjsing #include <stdio.h>
237ad73a06Sjsing #include <stdlib.h>
247ad73a06Sjsing #include <unistd.h>
257ad73a06Sjsing
267ad73a06Sjsing #include <openssl/x509.h>
277ad73a06Sjsing
287ad73a06Sjsing #include <tls.h>
297ad73a06Sjsing #include <tls_internal.h>
307ad73a06Sjsing
317ad73a06Sjsing #define PUBKEY_HASH \
32*0ba45550Sjsing "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9f"
337ad73a06Sjsing
347ad73a06Sjsing char *cert_file, *key_file, *ocsp_staple_file;
357ad73a06Sjsing
367ad73a06Sjsing static void
load_file(const char * filename,const uint8_t ** data,size_t * data_len)377ad73a06Sjsing load_file(const char *filename, const uint8_t **data, size_t *data_len)
387ad73a06Sjsing {
397ad73a06Sjsing struct stat sb;
407ad73a06Sjsing uint8_t *buf;
417ad73a06Sjsing size_t len;
427ad73a06Sjsing ssize_t n;
437ad73a06Sjsing int fd;
447ad73a06Sjsing
457ad73a06Sjsing if ((fd = open(filename, O_RDONLY)) == -1)
467ad73a06Sjsing err(1, "failed to open '%s'", filename);
477ad73a06Sjsing if ((fstat(fd, &sb)) == -1)
487ad73a06Sjsing err(1, "failed to stat '%s'", filename);
497ad73a06Sjsing if (sb.st_size < 0)
507ad73a06Sjsing err(1, "file size invalid for '%s'", filename);
517ad73a06Sjsing len = (size_t)sb.st_size;
527ad73a06Sjsing if ((buf = malloc(len)) == NULL)
537ad73a06Sjsing err(1, "out of memory");
547ad73a06Sjsing n = read(fd, buf, len);
557ad73a06Sjsing if (n < 0 || (size_t)n != len)
567ad73a06Sjsing err(1, "failed to read '%s'", filename);
577ad73a06Sjsing close(fd);
587ad73a06Sjsing
597ad73a06Sjsing *data = buf;
607ad73a06Sjsing *data_len = len;
617ad73a06Sjsing }
627ad73a06Sjsing
637ad73a06Sjsing static int
compare_mem(char * label,const uint8_t * data1,size_t data1_len,const uint8_t * data2,size_t data2_len)647ad73a06Sjsing compare_mem(char *label, const uint8_t *data1, size_t data1_len,
657ad73a06Sjsing const uint8_t *data2, size_t data2_len)
667ad73a06Sjsing {
677ad73a06Sjsing if (data1_len != data2_len) {
687ad73a06Sjsing fprintf(stderr, "FAIL: %s length mismatch (%zu != %zu)\n",
697ad73a06Sjsing label, data1_len, data2_len);
707ad73a06Sjsing return -1;
717ad73a06Sjsing }
727ad73a06Sjsing if (data1 == data2) {
737ad73a06Sjsing fprintf(stderr, "FAIL: %s comparing same memory (%p == %p)\n",
747ad73a06Sjsing label, data1, data2);
757ad73a06Sjsing return -1;
767ad73a06Sjsing }
777ad73a06Sjsing if (memcmp(data1, data2, data1_len) != 0) {
787ad73a06Sjsing fprintf(stderr, "FAIL: %s data mismatch\n", label);
797ad73a06Sjsing return -1;
807ad73a06Sjsing }
817ad73a06Sjsing return 0;
827ad73a06Sjsing }
837ad73a06Sjsing
847ad73a06Sjsing static int
do_keypair_tests(void)857ad73a06Sjsing do_keypair_tests(void)
867ad73a06Sjsing {
877ad73a06Sjsing size_t cert_len, key_len, ocsp_staple_len;
887ad73a06Sjsing const uint8_t *cert, *key, *ocsp_staple;
897ad73a06Sjsing X509 *x509_cert = NULL;
907ad73a06Sjsing struct tls_keypair *kp;
917ad73a06Sjsing struct tls_error err;
927ad73a06Sjsing int failed = 1;
937ad73a06Sjsing
947ad73a06Sjsing load_file(cert_file, &cert, &cert_len);
957ad73a06Sjsing load_file(key_file, &key, &key_len);
967ad73a06Sjsing load_file(ocsp_staple_file, &ocsp_staple, &ocsp_staple_len);
977ad73a06Sjsing
987ad73a06Sjsing if ((kp = tls_keypair_new()) == NULL) {
997ad73a06Sjsing fprintf(stderr, "FAIL: failed to create keypair\n");
1007ad73a06Sjsing goto done;
1017ad73a06Sjsing }
1027ad73a06Sjsing
1037ad73a06Sjsing if (tls_keypair_set_cert_file(kp, &err, cert_file) == -1) {
1047ad73a06Sjsing fprintf(stderr, "FAIL: failed to load cert file: %s\n",
1057ad73a06Sjsing err.msg);
1067ad73a06Sjsing goto done;
1077ad73a06Sjsing }
1087ad73a06Sjsing if (tls_keypair_set_key_file(kp, &err, key_file) == -1) {
1097ad73a06Sjsing fprintf(stderr, "FAIL: failed to load key file: %s\n", err.msg);
1107ad73a06Sjsing goto done;
1117ad73a06Sjsing }
1127ad73a06Sjsing if (tls_keypair_set_ocsp_staple_file(kp, &err, ocsp_staple_file) == -1) {
1137ad73a06Sjsing fprintf(stderr, "FAIL: failed to load ocsp staple file: %s\n",
1147ad73a06Sjsing err.msg);
1157ad73a06Sjsing goto done;
1167ad73a06Sjsing }
1177ad73a06Sjsing
1187ad73a06Sjsing if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
1197ad73a06Sjsing kp->cert_len) == -1)
1207ad73a06Sjsing goto done;
1217ad73a06Sjsing if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
1227ad73a06Sjsing goto done;
1237ad73a06Sjsing if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
1247ad73a06Sjsing kp->ocsp_staple, kp->ocsp_staple_len) == -1)
1257ad73a06Sjsing goto done;
126bfed3cd3Sjsing if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
127bfed3cd3Sjsing fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
128dc49573bStb kp->pubkey_hash, PUBKEY_HASH);
129bfed3cd3Sjsing goto done;
130bfed3cd3Sjsing }
1317ad73a06Sjsing
132dd7b7f28Sjsing tls_keypair_clear_key(kp);
1337ad73a06Sjsing
1347ad73a06Sjsing if (kp->key_mem != NULL || kp->key_len != 0) {
1357ad73a06Sjsing fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
1367ad73a06Sjsing kp->key_mem, kp->key_len);
1377ad73a06Sjsing goto done;
1387ad73a06Sjsing }
1397ad73a06Sjsing
140bfed3cd3Sjsing if (tls_keypair_set_cert_mem(kp, &err, cert, cert_len) == -1) {
1417ad73a06Sjsing fprintf(stderr, "FAIL: failed to load cert: %s\n", err.msg);
1427ad73a06Sjsing goto done;
1437ad73a06Sjsing }
144bfed3cd3Sjsing if (tls_keypair_set_key_mem(kp, &err, key, key_len) == -1) {
1457ad73a06Sjsing fprintf(stderr, "FAIL: failed to load key: %s\n", err.msg);
1467ad73a06Sjsing goto done;
1477ad73a06Sjsing }
148bfed3cd3Sjsing if (tls_keypair_set_ocsp_staple_mem(kp, &err, ocsp_staple,
1497ad73a06Sjsing ocsp_staple_len) == -1) {
1507ad73a06Sjsing fprintf(stderr, "FAIL: failed to load ocsp staple: %s\n", err.msg);
1517ad73a06Sjsing goto done;
1527ad73a06Sjsing }
1537ad73a06Sjsing if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
1547ad73a06Sjsing kp->cert_len) == -1)
1557ad73a06Sjsing goto done;
1567ad73a06Sjsing if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
1577ad73a06Sjsing goto done;
1587ad73a06Sjsing if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
1597ad73a06Sjsing kp->ocsp_staple, kp->ocsp_staple_len) == -1)
1607ad73a06Sjsing goto done;
161bfed3cd3Sjsing if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
1627ad73a06Sjsing fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
163dc49573bStb kp->pubkey_hash, PUBKEY_HASH);
1647ad73a06Sjsing goto done;
1657ad73a06Sjsing }
1667ad73a06Sjsing
1677ad73a06Sjsing if (tls_keypair_load_cert(kp, &err, &x509_cert) == -1) {
1687ad73a06Sjsing fprintf(stderr, "FAIL: failed to load X509 certificate: %s\n",
1697ad73a06Sjsing err.msg);
1707ad73a06Sjsing goto done;
1717ad73a06Sjsing }
1727ad73a06Sjsing
173dd7b7f28Sjsing tls_keypair_clear_key(kp);
1747ad73a06Sjsing
1757ad73a06Sjsing if (kp->key_mem != NULL || kp->key_len != 0) {
1767ad73a06Sjsing fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
1777ad73a06Sjsing kp->key_mem, kp->key_len);
1787ad73a06Sjsing goto done;
1797ad73a06Sjsing }
1807ad73a06Sjsing
1817ad73a06Sjsing failed = 0;
1827ad73a06Sjsing
1837ad73a06Sjsing done:
184dc49573bStb tls_keypair_free(kp);
1857ad73a06Sjsing X509_free(x509_cert);
186d23bdd73Stb free((uint8_t *)cert);
187d23bdd73Stb free((uint8_t *)key);
188d23bdd73Stb free((uint8_t *)ocsp_staple);
1897ad73a06Sjsing
1907ad73a06Sjsing return (failed);
1917ad73a06Sjsing }
1927ad73a06Sjsing
1937ad73a06Sjsing int
main(int argc,char ** argv)1947ad73a06Sjsing main(int argc, char **argv)
1957ad73a06Sjsing {
1967ad73a06Sjsing int failure = 0;
1977ad73a06Sjsing
1987ad73a06Sjsing if (argc != 4) {
1997ad73a06Sjsing fprintf(stderr, "usage: %s ocspstaplefile certfile keyfile\n",
2007ad73a06Sjsing argv[0]);
2017ad73a06Sjsing return (1);
2027ad73a06Sjsing }
2037ad73a06Sjsing
2047ad73a06Sjsing ocsp_staple_file = argv[1];
2057ad73a06Sjsing cert_file = argv[2];
2067ad73a06Sjsing key_file = argv[3];
2077ad73a06Sjsing
2087ad73a06Sjsing failure |= do_keypair_tests();
2097ad73a06Sjsing
2107ad73a06Sjsing return (failure);
2117ad73a06Sjsing }
212