Blob


1 /*
2 * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
3 * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
4 * Copyright (c) 2012 Gilles Chehade <gilles@poolp.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 */
19 #include "gmid.h"
21 #include <string.h>
23 #include <openssl/err.h>
24 #include <openssl/pem.h>
26 #include "log.h"
27 #include "proc.h"
29 #ifndef nitems
30 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
31 #endif
33 static void crypto_init(struct privsep *, struct privsep_proc *, void *);
34 static int crypto_dispatch_parent(int, struct privsep_proc *, struct imsg *);
35 static int crypto_dispatch_server(int, struct privsep_proc *, struct imsg *);
37 static struct privsep_proc procs[] = {
38 { "parent", PROC_PARENT, crypto_dispatch_parent },
39 { "server", PROC_SERVER, crypto_dispatch_server },
40 };
42 struct imsg_crypto_req {
43 uint64_t id;
44 char hash[TLS_CERT_HASH_SIZE];
45 size_t flen;
46 size_t tlen;
47 int padding;
48 /* followed by flen bytes of `from'. */
49 };
51 struct imsg_crypto_res {
52 uint64_t id;
53 int ret;
54 size_t len;
55 /* followed by len bytes of reply */
56 };
58 static uint64_t reqid;
59 static struct conf *conf;
61 void
62 crypto(struct privsep *ps, struct privsep_proc *p)
63 {
64 proc_run(ps, p, procs, nitems(procs), crypto_init, NULL);
65 }
67 static void
68 crypto_init(struct privsep *ps, struct privsep_proc *p, void *arg)
69 {
70 #if 0
71 static volatile int attached;
72 while (!attached) sleep(1);
73 #endif
75 conf = ps->ps_env;
77 sandbox_crypto_process();
78 }
80 static int
81 crypto_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
82 {
83 switch (imsg->hdr.type) {
84 case IMSG_RECONF_START:
85 case IMSG_RECONF_CERT:
86 case IMSG_RECONF_KEY:
87 case IMSG_RECONF_END:
88 if (config_recv(conf, imsg) == -1)
89 return -1;
90 break;
91 default:
92 return -1;
93 }
95 return 0;
96 }
98 static EVP_PKEY *
99 get_pkey(const char *hash)
101 struct pki *pki;
103 TAILQ_FOREACH(pki, &conf->pkis, pkis) {
104 if (!strcmp(pki->hash, hash))
105 return pki->pkey;
108 return NULL;
111 static int
112 crypto_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg)
114 struct privsep *ps = p->p_ps;
115 RSA *rsa = NULL;
116 EC_KEY *ecdsa = NULL;
117 EVP_PKEY *pkey;
118 struct imsg_crypto_req req;
119 struct imsg_crypto_res res;
120 struct ibuf ibuf;
121 struct iovec iov[2];
122 const void *from;
123 unsigned char *to;
124 int n, ret;
125 unsigned int len;
127 if (imsg_get_ibuf(imsg, &ibuf) == -1)
128 fatalx("%s: couldn't get an ibuf", __func__);
130 switch (imsg->hdr.type) {
131 case IMSG_CRYPTO_RSA_PRIVENC:
132 case IMSG_CRYPTO_RSA_PRIVDEC:
133 if (ibuf_get(&ibuf, &req, sizeof(req)) == -1 ||
134 ibuf_size(&ibuf) != req.flen)
135 fatalx("size mismatch for imsg %d", imsg->hdr.type);
136 from = ibuf_data(&ibuf);
138 if ((pkey = get_pkey(req.hash)) == NULL ||
139 (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
140 fatalx("invalid pkey hash");
142 if ((to = calloc(1, req.tlen)) == NULL)
143 fatal("calloc");
145 if (imsg->hdr.type == IMSG_CRYPTO_RSA_PRIVENC)
146 ret = RSA_private_encrypt(req.flen, from,
147 to, rsa, req.padding);
148 else
149 ret = RSA_private_decrypt(req.flen, from,
150 to, rsa, req.padding);
152 memset(&res, 0, sizeof(res));
153 res.id = req.id;
154 res.ret = ret;
156 memset(&iov, 0, sizeof(iov));
157 n = 0;
158 iov[n].iov_base = &res;
159 iov[n].iov_len = sizeof(res);
160 n++;
162 if (ret > 0) {
163 res.len = ret;
164 iov[n].iov_base = to;
165 iov[n].iov_len = ret;
166 n++;
169 log_debug("replying to server #%d", imsg->hdr.pid);
170 if (proc_composev_imsg(ps, PROC_SERVER, imsg->hdr.pid - 1,
171 imsg->hdr.type, 0, -1, iov, n) == -1)
172 fatal("proc_composev_imsg");
174 if (proc_flush_imsg(ps, PROC_SERVER, imsg->hdr.pid - 1) == -1)
175 fatal("proc_flush_imsg");
177 free(to);
178 RSA_free(rsa);
179 break;
181 case IMSG_CRYPTO_ECDSA_SIGN:
182 if (ibuf_get(&ibuf, &req, sizeof(req)) == -1 ||
183 ibuf_size(&ibuf) != req.flen)
184 fatalx("size mismatch for imsg %d", imsg->hdr.type);
185 from = ibuf_data(&ibuf);
187 if ((pkey = get_pkey(req.hash)) == NULL ||
188 (ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
189 fatalx("invalid pkey hash");
191 len = ECDSA_size(ecdsa);
192 if ((to = calloc(1, len)) == NULL)
193 fatal("calloc");
194 ret = ECDSA_sign(0, from, req.flen, to, &len, ecdsa);
196 memset(&res, 0, sizeof(res));
197 res.id = req.id;
198 res.ret = ret;
200 memset(&iov, 0, sizeof(iov));
201 n = 0;
202 iov[0].iov_base = &res;
203 iov[0].iov_len = sizeof(res);
204 n++;
206 if (ret > 0) {
207 res.len = len;
208 iov[n].iov_base = to;
209 iov[n].iov_len = len;
210 n++;
213 log_debug("replying to server #%d", imsg->hdr.pid);
214 if (proc_composev_imsg(ps, PROC_SERVER, imsg->hdr.pid - 1,
215 imsg->hdr.type, 0, -1, iov, n) == -1)
216 fatal("proc_composev_imsg");
218 if (proc_flush_imsg(ps, PROC_SERVER, imsg->hdr.pid - 1) == -1)
219 fatal("proc_flush_imsg");
221 free(to);
222 EC_KEY_free(ecdsa);
223 break;
225 default:
226 return -1;
229 return 0;
233 /*
234 * RSA privsep engine (called from unprivileged processes)
235 */
237 static const RSA_METHOD *rsa_default;
238 static RSA_METHOD *rsae_method;
240 static int
241 rsae_send_imsg(int flen, const unsigned char *from, unsigned char *to,
242 RSA *rsa, int padding, unsigned int cmd)
244 struct imsg_crypto_req req;
245 struct iovec iov[2];
246 struct imsg_crypto_res res;
247 struct imsgev *iev;
248 struct privsep_proc *p;
249 struct privsep *ps = conf->ps;
250 struct imsgbuf *imsgbuf;
251 struct imsg imsg;
252 struct ibuf ibuf;
253 int ret = 0;
254 int n, done = 0;
255 const void *toptr;
256 char *hash;
258 if ((hash = RSA_get_ex_data(rsa, 0)) == NULL)
259 return (0);
261 /*
262 * Send a synchronous imsg because we cannot defer the RSA
263 * operation in OpenSSL's engine layer.
264 */
265 memset(&req, 0, sizeof(req));
266 req.id = ++reqid;
267 if (strlcpy(req.hash, hash, sizeof(req.hash)) >= sizeof(req.hash))
268 fatalx("%s: hash too long (%zu)", __func__, strlen(hash));
269 req.flen = flen;
270 req.tlen = RSA_size(rsa);
271 req.padding = padding;
273 memset(&iov, 0, sizeof(iov));
274 iov[0].iov_base = &req;
275 iov[0].iov_len = sizeof(req);
276 iov[1].iov_base = (void *)from;
277 iov[1].iov_len = flen;
279 if (proc_composev(ps, PROC_CRYPTO, cmd, iov, 2) == -1)
280 fatal("proc_composev");
282 if (proc_flush_imsg(ps, PROC_CRYPTO, -1) == -1)
283 fatal("proc_flush_imsg");
285 iev = ps->ps_ievs[PROC_CRYPTO];
286 p = iev->proc;
287 imsgbuf = &iev->ibuf;
289 while (!done) {
290 if ((n = imsg_read(imsgbuf)) == -1 && errno != EAGAIN)
291 fatalx("imsg_read");
292 if (n == 0)
293 fatalx("pipe closed");
295 while (!done) {
296 if ((n = imsg_get(imsgbuf, &imsg)) == -1)
297 fatalx("imsg_get error");
298 if (n == 0)
299 break;
301 #if DEBUG > 1
302 log_debug(
303 "%s: %s %d got imsg %d id %d from %s %d",
304 __func__, title, 1, imsg_get_type(&imsg),
305 imsg_get_id(&imsg), "crypto", imsg_get_pid(&imsg));
306 #endif
308 if ((p->p_cb)(imsgbuf->fd, p, &imsg) == 0) {
309 /* Message was handled by the callback */
310 imsg_free(&imsg);
311 continue;
314 switch (imsg_get_type(&imsg)) {
315 case IMSG_CRYPTO_RSA_PRIVENC:
316 case IMSG_CRYPTO_RSA_PRIVDEC:
317 break;
318 default:
319 fatalx("%s: %s %d got invalid imsg %d"
320 " id %d from %s %d",
321 __func__, "server", ps->ps_instance + 1,
322 imsg_get_type(&imsg), imsg_get_id(&imsg),
323 "crypto", imsg_get_pid(&imsg));
326 if (imsg_get_ibuf(&imsg, &ibuf) == -1 ||
327 ibuf_get(&ibuf, &res, sizeof(res)) == -1 ||
328 (int)ibuf_size(&ibuf) != res.ret)
329 fatalx("size mismatch for imsg %d",
330 imsg.hdr.type);
331 ret = res.ret;
332 toptr = ibuf_data(&ibuf);
334 if (res.id != reqid)
335 fatalx("invalid id; got %llu, want %llu",
336 (unsigned long long)res.id,
337 (unsigned long long)reqid);
338 if (res.ret > 0)
339 memcpy(to, toptr, res.len);
341 done = 1;
343 imsg_free(&imsg);
346 imsg_event_add(iev);
348 return (ret);
351 static int
352 rsae_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,
353 int padding)
355 log_debug("debug: %s", __func__);
356 if (RSA_get_ex_data(rsa, 0) != NULL)
357 return (rsae_send_imsg(flen, from, to, rsa, padding,
358 IMSG_CRYPTO_RSA_PRIVENC));
359 return (RSA_meth_get_priv_enc(rsa_default)(flen, from, to, rsa, padding));
362 static int
363 rsae_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,
364 int padding)
366 log_debug("debug: %s", __func__);
367 if (RSA_get_ex_data(rsa, 0) != NULL)
368 return (rsae_send_imsg(flen, from, to, rsa, padding,
369 IMSG_CRYPTO_RSA_PRIVDEC));
371 return (RSA_meth_get_priv_dec(rsa_default)(flen, from, to, rsa, padding));
375 /*
376 * ECDSA privsep engine (called from unprivileged processes)
377 */
379 static const EC_KEY_METHOD *ecdsa_default;
380 static EC_KEY_METHOD *ecdsae_method;
382 static ECDSA_SIG *
383 ecdsae_send_enc_imsg(const unsigned char *dgst, int dgst_len,
384 const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey)
386 ECDSA_SIG *sig = NULL;
387 struct imsg_crypto_req req;
388 struct iovec iov[2];
389 struct imsg_crypto_res res;
390 struct imsgev *iev;
391 struct privsep_proc *p;
392 struct privsep *ps = conf->ps;
393 struct imsgbuf *imsgbuf;
394 struct imsg imsg;
395 struct ibuf ibuf;
396 int n, done = 0;
397 const void *toptr;
398 char *hash;
400 if ((hash = EC_KEY_get_ex_data(eckey, 0)) == NULL)
401 return (0);
403 /*
404 * Send a synchronous imsg because we cannot defer the RSA
405 * operation in OpenSSL's engine layer.
406 */
407 memset(&req, 0, sizeof(req));
408 req.id = ++reqid;
409 if (strlcpy(req.hash, hash, sizeof(req.hash)) >= sizeof(req.hash))
410 fatalx("%s: hash too long (%zu)", __func__, strlen(hash));
411 req.flen = dgst_len;
413 memset(&iov, 0, sizeof(iov));
414 iov[0].iov_base = &req;
415 iov[0].iov_len = sizeof(req);
416 iov[1].iov_base = (void *)dgst;
417 iov[1].iov_len = dgst_len;
419 if (proc_composev(ps, PROC_CRYPTO, IMSG_CRYPTO_ECDSA_SIGN, iov, 2) == -1)
420 fatal("proc_composev");
422 if (proc_flush_imsg(ps, PROC_CRYPTO, -1) == -1)
423 fatal("proc_flush_imsg");
425 iev = ps->ps_ievs[PROC_CRYPTO];
426 p = iev->proc;
427 imsgbuf = &iev->ibuf;
429 while (!done) {
430 if ((n = imsg_read(imsgbuf)) == -1 && errno != EAGAIN)
431 fatalx("imsg_read");
432 if (n == 0)
433 fatalx("pipe closed");
435 while (!done) {
436 if ((n = imsg_get(imsgbuf, &imsg)) == -1)
437 fatalx("imsg_get error");
438 if (n == 0)
439 break;
441 #if DEBUG > 1
442 log_debug(
443 "%s: %s %d got imsg %d peerid %d from %s %d",
444 __func__, title, 1, imsg.hdr.type,
445 imsg.hdr.peerid, "crypto", imsg.hdr.pid);
446 #endif
448 if (imsg.hdr.type != IMSG_CRYPTO_ECDSA_SIGN &&
449 crypto_dispatch_server(imsgbuf->fd, p, &imsg)
450 == 0) {
451 /* Message was handled by the callback */
452 imsg_free(&imsg);
453 continue;
456 if (imsg.hdr.type != IMSG_CRYPTO_ECDSA_SIGN)
457 fatalx("%s: %s %d got invalid imsg %d"
458 " peerid %d from %s %d",
459 __func__, "server", ps->ps_instance + 1,
460 imsg.hdr.type, imsg.hdr.peerid,
461 "crypto", imsg.hdr.pid);
463 if (imsg_get_ibuf(&imsg, &ibuf) == -1 ||
464 ibuf_get(&ibuf, &res, sizeof(res)) == -1 ||
465 ibuf_size(&ibuf) != res.len)
466 fatalx("size mismatch for imsg %d",
467 imsg.hdr.type);
469 toptr = ibuf_data(&ibuf);
471 if (res.id != reqid)
472 fatalx("invalid response id");
473 if (res.ret > 0) {
474 d2i_ECDSA_SIG(&sig,
475 (const unsigned char **)&toptr, res.len);
478 done = 1;
480 imsg_free(&imsg);
483 imsg_event_add(iev);
485 return (sig);
488 static ECDSA_SIG *
489 ecdsae_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
490 const BIGNUM *rp, EC_KEY *eckey)
492 ECDSA_SIG *(*psign_sig)(const unsigned char *, int, const BIGNUM *,
493 const BIGNUM *, EC_KEY *);
495 log_debug("debug: %s", __func__);
496 if (EC_KEY_get_ex_data(eckey, 0) != NULL)
497 return (ecdsae_send_enc_imsg(dgst, dgst_len, inv, rp, eckey));
498 EC_KEY_METHOD_get_sign(ecdsa_default, NULL, NULL, &psign_sig);
499 return (psign_sig(dgst, dgst_len, inv, rp, eckey));
503 /*
504 * Initialize the two engines.
505 */
507 static void
508 rsa_engine_init(void)
510 const char *errstr;
512 if ((rsa_default = RSA_get_default_method()) == NULL) {
513 errstr = "RSA_get_default_method";
514 goto fail;
517 if ((rsae_method = RSA_meth_dup(rsa_default)) == NULL) {
518 errstr = "RSA_meth_dup";
519 goto fail;
522 RSA_meth_set_priv_enc(rsae_method, rsae_priv_enc);
523 RSA_meth_set_priv_dec(rsae_method, rsae_priv_dec);
525 RSA_meth_set_flags(rsae_method,
526 RSA_meth_get_flags(rsa_default) | RSA_METHOD_FLAG_NO_CHECK);
527 RSA_meth_set0_app_data(rsae_method,
528 RSA_meth_get0_app_data(rsa_default));
530 RSA_set_default_method(rsae_method);
532 return;
534 fail:
535 ssl_error(errstr);
536 fatalx("%s", errstr);
539 static void
540 ecdsa_engine_init(void)
542 int (*sign)(int, const unsigned char *, int, unsigned char *,
543 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *);
544 int (*sign_setup)(EC_KEY *, BN_CTX *, BIGNUM **, BIGNUM **);
545 const char *errstr;
547 if ((ecdsa_default = EC_KEY_get_default_method()) == NULL) {
548 errstr = "EC_KEY_get_default_method";
549 goto fail;
552 if ((ecdsae_method = EC_KEY_METHOD_new(ecdsa_default)) == NULL) {
553 errstr = "EC_KEY_METHOD_new";
554 goto fail;
557 EC_KEY_METHOD_get_sign(ecdsa_default, &sign, &sign_setup, NULL);
558 EC_KEY_METHOD_set_sign(ecdsae_method, sign, sign_setup,
559 ecdsae_do_sign);
561 EC_KEY_set_default_method(ecdsae_method);
563 return;
565 fail:
566 ssl_error(errstr);
567 fatalx("%s", errstr);
570 void
571 crypto_engine_init(struct conf *c)
573 conf = c;
575 rsa_engine_init();
576 ecdsa_engine_init();