1 /* $OpenBSD: keypairtest.c,v 1.4 2018/04/07 16:42:17 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:858d0f94beb0a08eb4f13871ba57bf0a2e081287d0efbaeb3bbac59dd8f1a8e5"
33 
34 char *cert_file, *key_file, *ocsp_staple_file;
35 
36 static void
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
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
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 	char *hash = NULL;
93 	int failed = 1;
94 
95 	load_file(cert_file, &cert, &cert_len);
96 	load_file(key_file, &key, &key_len);
97 	load_file(ocsp_staple_file, &ocsp_staple, &ocsp_staple_len);
98 
99 	if ((kp = tls_keypair_new()) == NULL) {
100 		fprintf(stderr, "FAIL: failed to create keypair\n");
101 		goto done;
102 	}
103 
104 	if (tls_keypair_set_cert_file(kp, &err, cert_file) == -1) {
105 		fprintf(stderr, "FAIL: failed to load cert file: %s\n",
106 		    err.msg);
107 		goto done;
108 	}
109 	if (tls_keypair_set_key_file(kp, &err, key_file) == -1) {
110 		fprintf(stderr, "FAIL: failed to load key file: %s\n", err.msg);
111 		goto done;
112 	}
113 	if (tls_keypair_set_ocsp_staple_file(kp, &err, ocsp_staple_file) == -1) {
114 		fprintf(stderr, "FAIL: failed to load ocsp staple file: %s\n",
115 		    err.msg);
116 		goto done;
117 	}
118 
119 	if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
120 	    kp->cert_len) == -1)
121 		goto done;
122 	if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
123 		goto done;
124 	if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
125 	    kp->ocsp_staple, kp->ocsp_staple_len) == -1)
126 		goto done;
127 	if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
128 		fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
129 		    hash, PUBKEY_HASH);
130 		goto done;
131 	}
132 
133 	tls_keypair_clear_key(kp);
134 
135 	if (kp->key_mem != NULL || kp->key_len != 0) {
136 		fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
137 		    kp->key_mem, kp->key_len);
138 		goto done;
139 	}
140 
141 	if (tls_keypair_set_cert_mem(kp, &err, cert, cert_len) == -1) {
142 		fprintf(stderr, "FAIL: failed to load cert: %s\n", err.msg);
143 		goto done;
144 	}
145 	if (tls_keypair_set_key_mem(kp, &err, key, key_len) == -1) {
146 		fprintf(stderr, "FAIL: failed to load key: %s\n", err.msg);
147 		goto done;
148 	}
149 	if (tls_keypair_set_ocsp_staple_mem(kp, &err, ocsp_staple,
150 	    ocsp_staple_len) == -1) {
151 		fprintf(stderr, "FAIL: failed to load ocsp staple: %s\n", err.msg);
152 		goto done;
153 	}
154 	if (compare_mem("certificate", cert, cert_len, kp->cert_mem,
155 	    kp->cert_len) == -1)
156 		goto done;
157 	if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1)
158 		goto done;
159 	if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len,
160 	    kp->ocsp_staple, kp->ocsp_staple_len) == -1)
161 		goto done;
162 	if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) {
163 		fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'",
164 		    hash, PUBKEY_HASH);
165 		goto done;
166 	}
167 
168 	if (tls_keypair_load_cert(kp, &err, &x509_cert) == -1) {
169 		fprintf(stderr, "FAIL: failed to load X509 certificate: %s\n",
170 		    err.msg);
171 		goto done;
172 	}
173 
174 	tls_keypair_clear_key(kp);
175 
176 	if (kp->key_mem != NULL || kp->key_len != 0) {
177 		fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)",
178 		    kp->key_mem, kp->key_len);
179 		goto done;
180 	}
181 
182 	tls_keypair_free(kp);
183 
184 	failed = 0;
185 
186  done:
187 	X509_free(x509_cert);
188 	free(hash);
189 
190 	return (failed);
191 }
192 
193 int
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