1 /* $OpenBSD: keypairtest.c,v 1.7 2024/03/20 10:38:05 jsing Exp $ */
2 /*
3 * Copyright (c) 2018 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/stat.h>
19
20 #include <err.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 #include <openssl/x509.h>
27
28 #include <tls.h>
29 #include <tls_internal.h>
30
31 #define PUBKEY_HASH \
32 "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9f"
33
34 char *cert_file, *key_file, *ocsp_staple_file;
35
36 static void
load_file(const char * filename,const uint8_t ** data,size_t * data_len)37 load_file(const char *filename, const uint8_t **data, size_t *data_len)
38 {
39 struct stat sb;
40 uint8_t *buf;
41 size_t len;
42 ssize_t n;
43 int fd;
44
45 if ((fd = open(filename, O_RDONLY)) == -1)
46 err(1, "failed to open '%s'", filename);
47 if ((fstat(fd, &sb)) == -1)
48 err(1, "failed to stat '%s'", filename);
49 if (sb.st_size < 0)
50 err(1, "file size invalid for '%s'", filename);
51 len = (size_t)sb.st_size;
52 if ((buf = malloc(len)) == NULL)
53 err(1, "out of memory");
54 n = read(fd, buf, len);
55 if (n < 0 || (size_t)n != len)
56 err(1, "failed to read '%s'", filename);
57 close(fd);
58
59 *data = buf;
60 *data_len = len;
61 }
62
63 static int
compare_mem(char * label,const uint8_t * data1,size_t data1_len,const uint8_t * data2,size_t data2_len)64 compare_mem(char *label, const uint8_t *data1, size_t data1_len,
65 const uint8_t *data2, size_t data2_len)
66 {
67 if (data1_len != data2_len) {
68 fprintf(stderr, "FAIL: %s length mismatch (%zu != %zu)\n",
69 label, data1_len, data2_len);
70 return -1;
71 }
72 if (data1 == data2) {
73 fprintf(stderr, "FAIL: %s comparing same memory (%p == %p)\n",
74 label, data1, data2);
75 return -1;
76 }
77 if (memcmp(data1, data2, data1_len) != 0) {
78 fprintf(stderr, "FAIL: %s data mismatch\n", label);
79 return -1;
80 }
81 return 0;
82 }
83
84 static int
do_keypair_tests(void)85 do_keypair_tests(void)
86 {
87 size_t cert_len, key_len, ocsp_staple_len;
88 const uint8_t *cert, *key, *ocsp_staple;
89 X509 *x509_cert = NULL;
90 struct tls_keypair *kp;
91 struct tls_error err;
92 int failed = 1;
93
94 load_file(cert_file, &cert, &cert_len);
95 load_file(key_file, &key, &key_len);
96 load_file(ocsp_staple_file, &ocsp_staple, &ocsp_staple_len);
97
98 if ((kp = tls_keypair_new()) == NULL) {
99 fprintf(stderr, "FAIL: failed to create keypair\n");
100 goto done;
101 }
102
103 if (tls_keypair_set_cert_file(kp, &err, cert_file) == -1) {
104 fprintf(stderr, "FAIL: failed to load cert file: %s\n",
105 err.msg);
106 goto done;
107 }
108 if (tls_keypair_set_key_file(kp, &err, key_file) == -1) {
109 fprintf(stderr, "FAIL: failed to load key file: %s\n", err.msg);
110 goto done;
111 }
112 if (tls_keypair_set_ocsp_staple_file(kp, &err, ocsp_staple_file) == -1) {
113 fprintf(stderr, "FAIL: failed to load ocsp staple file: %s\n",
114 err.msg);
115 goto done;
116 }
117
118 if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
119 kp->cert_len) == -1)
120 goto done;
121 if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
122 goto done;
123 if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
124 kp->ocsp_staple, kp->ocsp_staple_len) == -1)
125 goto done;
126 if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
127 fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
128 kp->pubkey_hash, PUBKEY_HASH);
129 goto done;
130 }
131
132 tls_keypair_clear_key(kp);
133
134 if (kp->key_mem != NULL || kp->key_len != 0) {
135 fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
136 kp->key_mem, kp->key_len);
137 goto done;
138 }
139
140 if (tls_keypair_set_cert_mem(kp, &err, cert, cert_len) == -1) {
141 fprintf(stderr, "FAIL: failed to load cert: %s\n", err.msg);
142 goto done;
143 }
144 if (tls_keypair_set_key_mem(kp, &err, key, key_len) == -1) {
145 fprintf(stderr, "FAIL: failed to load key: %s\n", err.msg);
146 goto done;
147 }
148 if (tls_keypair_set_ocsp_staple_mem(kp, &err, ocsp_staple,
149 ocsp_staple_len) == -1) {
150 fprintf(stderr, "FAIL: failed to load ocsp staple: %s\n", err.msg);
151 goto done;
152 }
153 if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
154 kp->cert_len) == -1)
155 goto done;
156 if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
157 goto done;
158 if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
159 kp->ocsp_staple, kp->ocsp_staple_len) == -1)
160 goto done;
161 if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
162 fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
163 kp->pubkey_hash, PUBKEY_HASH);
164 goto done;
165 }
166
167 if (tls_keypair_load_cert(kp, &err, &x509_cert) == -1) {
168 fprintf(stderr, "FAIL: failed to load X509 certificate: %s\n",
169 err.msg);
170 goto done;
171 }
172
173 tls_keypair_clear_key(kp);
174
175 if (kp->key_mem != NULL || kp->key_len != 0) {
176 fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
177 kp->key_mem, kp->key_len);
178 goto done;
179 }
180
181 failed = 0;
182
183 done:
184 tls_keypair_free(kp);
185 X509_free(x509_cert);
186 free((uint8_t *)cert);
187 free((uint8_t *)key);
188 free((uint8_t *)ocsp_staple);
189
190 return (failed);
191 }
192
193 int
main(int argc,char ** argv)194 main(int argc, char **argv)
195 {
196 int failure = 0;
197
198 if (argc != 4) {
199 fprintf(stderr, "usage: %s ocspstaplefile certfile keyfile\n",
200 argv[0]);
201 return (1);
202 }
203
204 ocsp_staple_file = argv[1];
205 cert_file = argv[2];
206 key_file = argv[3];
207
208 failure |= do_keypair_tests();
209
210 return (failure);
211 }
212