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 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 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 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 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 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 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 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 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 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 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