xref: /openbsd-src/usr.sbin/relayd/ssl.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: ssl.c,v 1.34 2017/07/28 13:58:52 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
5  * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/uio.h>
23 
24 #include <unistd.h>
25 #include <string.h>
26 #include <imsg.h>
27 
28 #include <openssl/ssl.h>
29 #include <openssl/err.h>
30 #include <openssl/engine.h>
31 
32 #include "relayd.h"
33 #include "boguskeys.h"
34 
35 int	ssl_password_cb(char *, int, int, void *);
36 
37 void
38 ssl_init(struct relayd *env)
39 {
40 	static int	 initialized = 0;
41 
42 	if (initialized)
43 		return;
44 
45 	SSL_library_init();
46 	SSL_load_error_strings();
47 
48 	/* Init hardware crypto engines. */
49 	ENGINE_load_builtin_engines();
50 	ENGINE_register_all_complete();
51 
52 	initialized = 1;
53 }
54 
55 int
56 ssl_password_cb(char *buf, int size, int rwflag, void *u)
57 {
58 	size_t	len;
59 	if (u == NULL) {
60 		bzero(buf, size);
61 		return (0);
62 	}
63 	if ((len = strlcpy(buf, u, size)) >= (size_t)size)
64 		return (0);
65 	return (len);
66 }
67 
68 char *
69 ssl_load_key(struct relayd *env, const char *name, off_t *len, char *pass)
70 {
71 	FILE		*fp;
72 	EVP_PKEY	*key = NULL;
73 	BIO		*bio = NULL;
74 	long		 size;
75 	char		*data, *buf = NULL;
76 
77 	/* Initialize SSL library once */
78 	ssl_init(env);
79 
80 	/*
81 	 * Read (possibly) encrypted key from file
82 	 */
83 	if ((fp = fopen(name, "r")) == NULL)
84 		return (NULL);
85 
86 	key = PEM_read_PrivateKey(fp, NULL, ssl_password_cb, pass);
87 	fclose(fp);
88 	if (key == NULL)
89 		goto fail;
90 
91 	/*
92 	 * Write unencrypted key to memory buffer
93 	 */
94 	if ((bio = BIO_new(BIO_s_mem())) == NULL)
95 		goto fail;
96 	if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL))
97 		goto fail;
98 	if ((size = BIO_get_mem_data(bio, &data)) <= 0)
99 		goto fail;
100 	if ((buf = calloc(1, size)) == NULL)
101 		goto fail;
102 	memcpy(buf, data, size);
103 
104 	BIO_free_all(bio);
105 	EVP_PKEY_free(key);
106 
107 	*len = (off_t)size;
108 	return (buf);
109 
110  fail:
111 	free(buf);
112 	if (bio != NULL)
113 		BIO_free_all(bio);
114 	if (key != NULL)
115 		EVP_PKEY_free(key);
116 	return (NULL);
117 }
118 
119 uint8_t *
120 ssl_update_certificate(const uint8_t *oldcert, size_t oldlen, EVP_PKEY *pkey,
121     EVP_PKEY *capkey, X509 *cacert, size_t *newlen)
122 {
123 	char		 name[2][TLS_NAME_SIZE];
124 	BIO		*in, *out = NULL;
125 	BUF_MEM		*bptr = NULL;
126 	X509		*cert = NULL;
127 	uint8_t		*newcert = NULL, *foo = NULL;
128 
129 	/* XXX BIO_new_mem_buf is not using const so work around this */
130 	if ((foo = malloc(oldlen)) == NULL) {
131 		log_warn("%s: malloc", __func__);
132 		return (NULL);
133 	}
134 	memcpy(foo, oldcert, oldlen);
135 
136 	if ((in = BIO_new_mem_buf(foo, oldlen)) == NULL) {
137 		log_warnx("%s: BIO_new_mem_buf failed", __func__);
138 		goto done;
139 	}
140 
141 	if ((cert = PEM_read_bio_X509(in, NULL,
142 	    ssl_password_cb, NULL)) == NULL) {
143 		log_warnx("%s: PEM_read_bio_X509 failed", __func__);
144 		goto done;
145 	}
146 
147 	BIO_free(in);
148 	in = NULL;
149 
150 	name[0][0] = name[1][0] = '\0';
151 	if (!X509_NAME_oneline(X509_get_subject_name(cert),
152 	    name[0], sizeof(name[0])) ||
153 	    !X509_NAME_oneline(X509_get_issuer_name(cert),
154 	    name[1], sizeof(name[1])))
155 		goto done;
156 
157 	if ((cert = X509_dup(cert)) == NULL)
158 		goto done;
159 
160 	/* Update certificate key and use our CA as the issuer */
161 	X509_set_pubkey(cert, pkey);
162 	X509_set_issuer_name(cert, X509_get_subject_name(cacert));
163 
164 	/* Sign with our CA */
165 	if (!X509_sign(cert, capkey, EVP_sha256())) {
166 		log_warnx("%s: X509_sign failed", __func__);
167 		goto done;
168 	}
169 
170 #if DEBUG_CERT
171 	log_debug("%s: subject %s", __func__, name[0]);
172 	log_debug("%s: issuer %s", __func__, name[1]);
173 #if DEBUG > 2
174 	X509_print_fp(stdout, cert);
175 #endif
176 #endif
177 
178 	/* write cert as PEM file */
179 	out = BIO_new(BIO_s_mem());
180 	if (out == NULL) {
181 		log_warnx("%s: BIO_new failed", __func__);
182 		goto done;
183 	}
184 	if (!PEM_write_bio_X509(out, cert)) {
185 		log_warnx("%s: PEM_write_bio_X509 failed", __func__);
186 		goto done;
187 	}
188 	BIO_get_mem_ptr(out, &bptr);
189 	if ((newcert = malloc(bptr->length)) == NULL) {
190 		log_warn("%s: malloc", __func__);
191 		goto done;
192 	}
193 	memcpy(newcert, bptr->data, bptr->length);
194 	*newlen = bptr->length;
195 
196 done:
197 	free(foo);
198 	if (in)
199 		BIO_free(in);
200 	if (out)
201 		BIO_free(out);
202 	if (cert)
203 		X509_free(cert);
204 	return (newcert);
205 }
206 
207 int
208 ssl_load_pkey(char *buf, off_t len, X509 **x509ptr, EVP_PKEY **pkeyptr)
209 {
210 	BIO		*in;
211 	X509		*x509 = NULL;
212 	EVP_PKEY	*pkey = NULL;
213 	RSA		*rsa = NULL;
214 	char		*hash = NULL;
215 
216 	if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
217 		log_warnx("%s: BIO_new_mem_buf failed", __func__);
218 		return (0);
219 	}
220 	if ((x509 = PEM_read_bio_X509(in, NULL,
221 	    ssl_password_cb, NULL)) == NULL) {
222 		log_warnx("%s: PEM_read_bio_X509 failed", __func__);
223 		goto fail;
224 	}
225 	if ((pkey = X509_get_pubkey(x509)) == NULL) {
226 		log_warnx("%s: X509_get_pubkey failed", __func__);
227 		goto fail;
228 	}
229 	if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
230 		log_warnx("%s: failed to extract RSA", __func__);
231 		goto fail;
232 	}
233 	if ((hash = malloc(TLS_CERT_HASH_SIZE)) == NULL) {
234 		log_warn("%s: allocate hash failed", __func__);
235 		goto fail;
236 	}
237 	hash_x509(x509, hash, TLS_CERT_HASH_SIZE);
238 	if (RSA_set_ex_data(rsa, 0, hash) != 1) {
239 		log_warnx("%s: failed to set hash as exdata", __func__);
240 		goto fail;
241 	}
242 
243 	RSA_free(rsa); /* dereference, will be cleaned up with pkey */
244 	*pkeyptr = pkey;
245 	if (x509ptr != NULL)
246 		*x509ptr = x509;
247 	else
248 		X509_free(x509);
249 	BIO_free(in);
250 
251 	return (1);
252 
253  fail:
254 	free(hash);
255 	if (rsa != NULL)
256 		RSA_free(rsa);
257 	if (pkey != NULL)
258 		EVP_PKEY_free(pkey);
259 	if (x509 != NULL)
260 		X509_free(x509);
261 	BIO_free(in);
262 
263 	return (0);
264 }
265 
266 /*
267  * This function is a horrible hack but for RSA privsep to work a private key
268  * with correct size needs to be loaded into the tls config.
269  */
270 int
271 ssl_ctx_fake_private_key(char *buf, off_t len, const char **fake_key)
272 {
273 	BIO		*in;
274 	EVP_PKEY	*pkey = NULL;
275 	X509		*x509 = NULL;
276 	int		 ret = -1, keylen;
277 
278 	if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
279 		log_warnx("%s: BIO_new_mem_buf failed", __func__);
280 		return (0);
281 	}
282 
283 	if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
284 		log_warnx("%s: PEM_read_bio_X509 failed", __func__);
285 		goto fail;
286 	}
287 
288 	if ((pkey = X509_get_pubkey(x509)) == NULL) {
289 		log_warnx("%s: X509_get_pubkey failed", __func__);
290 		goto fail;
291 	}
292 
293 	keylen = EVP_PKEY_size(pkey) * 8;
294 	switch(keylen) {
295 	case 1024:
296 		*fake_key = bogus_1024;
297 		ret = sizeof(bogus_1024);
298 		break;
299 	case 2048:
300 		*fake_key = bogus_2048;
301 		ret = sizeof(bogus_2048);
302 		break;
303 	case 4096:
304 		*fake_key = bogus_4096;
305 		ret = sizeof(bogus_4096);
306 		break;
307 	case 8192:
308 		*fake_key = bogus_8192;
309 		ret = sizeof(bogus_8192);
310 		break;
311 	default:
312 		log_warnx("%s: key size %d not support", __func__, keylen);
313 		ret = -1;
314 		break;
315 	}
316 fail:
317 	BIO_free(in);
318 
319 	if (pkey != NULL)
320 		EVP_PKEY_free(pkey);
321 	if (x509 != NULL)
322 		X509_free(x509);
323 
324 	return (ret);
325 }
326