1 /* $OpenBSD: ca.c,v 1.45 2024/11/21 13:21:34 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/uio.h>
22
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <poll.h>
27 #include <imsg.h>
28
29 #include <openssl/bio.h>
30 #include <openssl/err.h>
31 #include <openssl/evp.h>
32 #include <openssl/pem.h>
33 #include <openssl/rsa.h>
34 #include <openssl/engine.h>
35
36 #include "relayd.h"
37
38 void ca_init(struct privsep *, struct privsep_proc *p, void *);
39 void ca_launch(void);
40
41 int ca_dispatch_parent(int, struct privsep_proc *, struct imsg *);
42 int ca_dispatch_relay(int, struct privsep_proc *, struct imsg *);
43
44 int rsae_priv_enc(int, const u_char *, u_char *, RSA *, int);
45 int rsae_priv_dec(int, const u_char *, u_char *, RSA *, int);
46
47 static struct relayd *env = NULL;
48
49 static struct privsep_proc procs[] = {
50 { "parent", PROC_PARENT, ca_dispatch_parent },
51 { "relay", PROC_RELAY, ca_dispatch_relay },
52 };
53
54 void
ca(struct privsep * ps,struct privsep_proc * p)55 ca(struct privsep *ps, struct privsep_proc *p)
56 {
57 env = ps->ps_env;
58
59 proc_run(ps, p, procs, nitems(procs), ca_init, NULL);
60 }
61
62 void
ca_init(struct privsep * ps,struct privsep_proc * p,void * arg)63 ca_init(struct privsep *ps, struct privsep_proc *p, void *arg)
64 {
65 if (pledge("stdio recvfd", NULL) == -1)
66 fatal("pledge");
67
68 if (config_init(ps->ps_env) == -1)
69 fatal("failed to initialize configuration");
70
71 env->sc_id = getpid() & 0xffff;
72 }
73
74 void
hash_x509(X509 * cert,char * hash,size_t hashlen)75 hash_x509(X509 *cert, char *hash, size_t hashlen)
76 {
77 static const char hex[] = "0123456789abcdef";
78 size_t off;
79 char digest[EVP_MAX_MD_SIZE];
80 int dlen, i;
81
82 if (X509_pubkey_digest(cert, EVP_sha256(), digest, &dlen) != 1)
83 fatalx("%s: X509_pubkey_digest failed", __func__);
84
85 if (hashlen < 2 * dlen + sizeof("SHA256:"))
86 fatalx("%s: hash buffer too small", __func__);
87
88 off = strlcpy(hash, "SHA256:", hashlen);
89
90 for (i = 0; i < dlen; i++) {
91 hash[off++] = hex[(digest[i] >> 4) & 0x0f];
92 hash[off++] = hex[digest[i] & 0x0f];
93 }
94 hash[off] = 0;
95 }
96
97 void
ca_launch(void)98 ca_launch(void)
99 {
100 char hash[TLS_CERT_HASH_SIZE];
101 char *buf;
102 BIO *in = NULL;
103 EVP_PKEY *pkey = NULL;
104 struct relay *rlay;
105 struct relay_cert *cert;
106 X509 *x509 = NULL;
107 off_t len;
108
109 TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
110 if (cert->cert_fd == -1 || cert->cert_key_fd == -1)
111 continue;
112
113 if ((buf = relay_load_fd(cert->cert_fd, &len)) == NULL)
114 fatal("ca_launch: cert relay_load_fd");
115
116 if ((in = BIO_new_mem_buf(buf, len)) == NULL)
117 fatalx("ca_launch: cert BIO_new_mem_buf");
118
119 if ((x509 = PEM_read_bio_X509(in, NULL,
120 NULL, NULL)) == NULL)
121 fatalx("ca_launch: cert PEM_read_bio_X509");
122
123 hash_x509(x509, hash, sizeof(hash));
124
125 BIO_free(in);
126 X509_free(x509);
127 purge_key(&buf, len);
128
129 if ((buf = relay_load_fd(cert->cert_key_fd, &len)) == NULL)
130 fatal("ca_launch: key relay_load_fd");
131
132 if ((in = BIO_new_mem_buf(buf, len)) == NULL)
133 fatalx("%s: key", __func__);
134
135 if ((pkey = PEM_read_bio_PrivateKey(in,
136 NULL, NULL, NULL)) == NULL)
137 fatalx("%s: PEM", __func__);
138
139 cert->cert_pkey = pkey;
140
141 if (pkey_add(env, pkey, hash) == NULL)
142 fatalx("tls pkey");
143
144 BIO_free(in);
145 purge_key(&buf, len);
146 }
147
148 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) {
149 if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) == 0)
150 continue;
151
152 if (rlay->rl_tls_cacert_fd != -1 &&
153 rlay->rl_conf.tls_cakey_len) {
154 if ((buf = relay_load_fd(rlay->rl_tls_cacert_fd,
155 &len)) == NULL)
156 fatal("ca_launch: cacert relay_load_fd");
157
158 if ((in = BIO_new_mem_buf(buf, len)) == NULL)
159 fatalx("ca_launch: cacert BIO_new_mem_buf");
160
161 if ((x509 = PEM_read_bio_X509(in, NULL,
162 NULL, NULL)) == NULL)
163 fatalx("ca_launch: cacert PEM_read_bio_X509");
164
165 hash_x509(x509, hash, sizeof(hash));
166
167 BIO_free(in);
168 X509_free(x509);
169 purge_key(&buf, len);
170
171 if ((in = BIO_new_mem_buf(rlay->rl_tls_cakey,
172 rlay->rl_conf.tls_cakey_len)) == NULL)
173 fatalx("%s: key", __func__);
174
175 if ((pkey = PEM_read_bio_PrivateKey(in,
176 NULL, NULL, NULL)) == NULL)
177 fatalx("%s: PEM", __func__);
178 BIO_free(in);
179
180 rlay->rl_tls_capkey = pkey;
181
182 if (pkey_add(env, pkey, hash) == NULL)
183 fatalx("ca pkey");
184
185 purge_key(&rlay->rl_tls_cakey,
186 rlay->rl_conf.tls_cakey_len);
187 }
188 close(rlay->rl_tls_ca_fd);
189 }
190 }
191
192 int
ca_dispatch_parent(int fd,struct privsep_proc * p,struct imsg * imsg)193 ca_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
194 {
195 switch (imsg->hdr.type) {
196 case IMSG_CFG_RELAY:
197 config_getrelay(env, imsg);
198 break;
199 case IMSG_CFG_RELAY_FD:
200 config_getrelayfd(env, imsg);
201 break;
202 case IMSG_CFG_DONE:
203 config_getcfg(env, imsg);
204 break;
205 case IMSG_CTL_START:
206 ca_launch();
207 break;
208 case IMSG_CTL_RESET:
209 config_getreset(env, imsg);
210 break;
211 default:
212 return -1;
213 }
214
215 return 0;
216 }
217
218 int
ca_dispatch_relay(int fd,struct privsep_proc * p,struct imsg * imsg)219 ca_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg)
220 {
221 struct ctl_keyop cko;
222 EVP_PKEY *pkey;
223 RSA *rsa;
224 u_char *from = NULL, *to = NULL;
225 struct iovec iov[2];
226 int c = 0;
227
228 switch (imsg->hdr.type) {
229 case IMSG_CA_PRIVENC:
230 case IMSG_CA_PRIVDEC:
231 IMSG_SIZE_CHECK(imsg, (&cko));
232 bcopy(imsg->data, &cko, sizeof(cko));
233 if (cko.cko_proc > env->sc_conf.prefork_relay)
234 fatalx("%s: invalid relay proc", __func__);
235 if (IMSG_DATA_SIZE(imsg) != (sizeof(cko) + cko.cko_flen))
236 fatalx("%s: invalid key operation", __func__);
237 if ((pkey = pkey_find(env, cko.cko_hash)) == NULL)
238 fatalx("%s: invalid relay hash '%s'",
239 __func__, cko.cko_hash);
240 if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
241 fatalx("%s: invalid relay key", __func__);
242
243 DPRINTF("%s:%d: key hash %s proc %d",
244 __func__, __LINE__, cko.cko_hash, cko.cko_proc);
245
246 from = (u_char *)imsg->data + sizeof(cko);
247 if ((to = calloc(1, cko.cko_tlen)) == NULL)
248 fatalx("%s: calloc", __func__);
249
250 switch (imsg->hdr.type) {
251 case IMSG_CA_PRIVENC:
252 cko.cko_tlen = RSA_private_encrypt(cko.cko_flen,
253 from, to, rsa, cko.cko_padding);
254 break;
255 case IMSG_CA_PRIVDEC:
256 cko.cko_tlen = RSA_private_decrypt(cko.cko_flen,
257 from, to, rsa, cko.cko_padding);
258 break;
259 }
260
261 if (cko.cko_tlen == -1) {
262 char buf[256];
263 log_warnx("%s: %s", __func__,
264 ERR_error_string(ERR_get_error(), buf));
265 }
266
267 iov[c].iov_base = &cko;
268 iov[c++].iov_len = sizeof(cko);
269 if (cko.cko_tlen > 0) {
270 iov[c].iov_base = to;
271 iov[c++].iov_len = cko.cko_tlen;
272 }
273
274 if (proc_composev_imsg(env->sc_ps, PROC_RELAY, cko.cko_proc,
275 imsg->hdr.type, -1, -1, iov, c) == -1)
276 log_warn("%s: proc_composev_imsg", __func__);
277
278 free(to);
279 RSA_free(rsa);
280 break;
281 default:
282 return -1;
283 }
284
285 return 0;
286 }
287
288 /*
289 * RSA privsep engine (called from unprivileged processes)
290 */
291
292 static const RSA_METHOD *rsa_default;
293 static RSA_METHOD *rsae_method;
294
295 static int
rsae_send_imsg(int flen,const u_char * from,u_char * to,RSA * rsa,int padding,u_int cmd)296 rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
297 int padding, u_int cmd)
298 {
299 struct privsep *ps = env->sc_ps;
300 struct pollfd pfd[1];
301 struct ctl_keyop cko;
302 int ret = 0;
303 char *hash;
304 struct iovec iov[2];
305 struct imsgbuf *ibuf;
306 struct imsgev *iev;
307 struct imsg imsg;
308 int n, done = 0, cnt = 0;
309 u_char *toptr;
310 static u_int seq = 0;
311
312 if ((hash = RSA_get_ex_data(rsa, 0)) == NULL)
313 return 0;
314
315 iev = proc_iev(ps, PROC_CA, ps->ps_instance);
316 ibuf = &iev->ibuf;
317
318 /*
319 * XXX this could be nicer...
320 */
321
322 (void)strlcpy(cko.cko_hash, hash, sizeof(cko.cko_hash));
323 cko.cko_proc = ps->ps_instance;
324 cko.cko_flen = flen;
325 cko.cko_tlen = RSA_size(rsa);
326 cko.cko_padding = padding;
327 cko.cko_cookie = seq++;
328
329 iov[cnt].iov_base = &cko;
330 iov[cnt++].iov_len = sizeof(cko);
331 iov[cnt].iov_base = (void *)(uintptr_t)from;
332 iov[cnt++].iov_len = flen;
333
334 /*
335 * Send a synchronous imsg because we cannot defer the RSA
336 * operation in OpenSSL's engine layer.
337 */
338 if (imsg_composev(ibuf, cmd, 0, 0, -1, iov, cnt) == -1)
339 log_warn("%s: imsg_composev", __func__);
340 if (imsgbuf_flush(ibuf) == -1)
341 log_warn("%s: imsgbuf_flush", __func__);
342
343 pfd[0].fd = ibuf->fd;
344 pfd[0].events = POLLIN;
345 while (!done) {
346 switch (poll(pfd, 1, RELAY_TLS_PRIV_TIMEOUT)) {
347 case -1:
348 if (errno != EINTR)
349 fatal("%s: poll", __func__);
350 continue;
351 case 0:
352 log_warnx("%s: priv%s poll timeout, keyop #%x",
353 __func__,
354 cmd == IMSG_CA_PRIVENC ? "enc" : "dec",
355 cko.cko_cookie);
356 return -1;
357 default:
358 break;
359 }
360 if ((n = imsgbuf_read(ibuf)) == -1)
361 fatalx("imsgbuf_read");
362 if (n == 0)
363 fatalx("pipe closed");
364
365 while (!done) {
366 if ((n = imsg_get(ibuf, &imsg)) == -1)
367 fatalx("imsg_get error");
368 if (n == 0)
369 break;
370
371 IMSG_SIZE_CHECK(&imsg, (&cko));
372 memcpy(&cko, imsg.data, sizeof(cko));
373
374 /*
375 * Due to earlier timed out requests, there may be
376 * responses that need to be skipped.
377 */
378 if (cko.cko_cookie != seq - 1) {
379 log_warnx(
380 "%s: priv%s obsolete keyop #%x", __func__,
381 cmd == IMSG_CA_PRIVENC ? "enc" : "dec",
382 cko.cko_cookie);
383 continue;
384 }
385
386 if (imsg.hdr.type != cmd)
387 fatalx("invalid response");
388
389 ret = cko.cko_tlen;
390 if (ret > 0) {
391 if (IMSG_DATA_SIZE(&imsg) !=
392 (sizeof(cko) + ret))
393 fatalx("data size");
394 toptr = (u_char *)imsg.data + sizeof(cko);
395 memcpy(to, toptr, ret);
396 }
397 done = 1;
398
399 imsg_free(&imsg);
400 }
401 }
402 imsg_event_add(iev);
403
404 return ret;
405 }
406
407 int
rsae_priv_enc(int flen,const u_char * from,u_char * to,RSA * rsa,int padding)408 rsae_priv_enc(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
409 {
410 DPRINTF("%s:%d", __func__, __LINE__);
411 return rsae_send_imsg(flen, from, to, rsa, padding, IMSG_CA_PRIVENC);
412 }
413
414 int
rsae_priv_dec(int flen,const u_char * from,u_char * to,RSA * rsa,int padding)415 rsae_priv_dec(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
416 {
417 DPRINTF("%s:%d", __func__, __LINE__);
418 return rsae_send_imsg(flen, from, to, rsa, padding, IMSG_CA_PRIVDEC);
419 }
420
421 void
ca_engine_init(struct relayd * x_env)422 ca_engine_init(struct relayd *x_env)
423 {
424 const char *errstr;
425
426 if (env == NULL)
427 env = x_env;
428
429 if (rsa_default != NULL)
430 return;
431
432 if ((rsa_default = RSA_get_default_method()) == NULL) {
433 errstr = "RSA_get_default_method";
434 goto fail;
435 }
436
437 if ((rsae_method = RSA_meth_dup(rsa_default)) == NULL) {
438 errstr = "RSA_meth_dup";
439 goto fail;
440 }
441
442 RSA_meth_set_priv_enc(rsae_method, rsae_priv_enc);
443 RSA_meth_set_priv_dec(rsae_method, rsae_priv_dec);
444
445 RSA_meth_set_flags(rsae_method,
446 RSA_meth_get_flags(rsa_default) | RSA_METHOD_FLAG_NO_CHECK);
447 RSA_meth_set0_app_data(rsae_method,
448 RSA_meth_get0_app_data(rsa_default));
449
450 RSA_set_default_method(rsae_method);
451
452 return;
453
454 fail:
455 RSA_meth_free(rsae_method);
456 fatalx("%s: %s", __func__, errstr);
457 }
458