1 /* $OpenBSD: ssl.c,v 1.37 2011/09/01 19:56:49 eric Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2008 Reyk Floeter <reyk@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/tree.h> 23 #include <sys/param.h> 24 #include <sys/socket.h> 25 #include <sys/stat.h> 26 27 #include <ctype.h> 28 #include <event.h> 29 #include <fcntl.h> 30 #include <imsg.h> 31 #include <pwd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <unistd.h> 36 37 #include <openssl/ssl.h> 38 #include <openssl/engine.h> 39 #include <openssl/err.h> 40 41 #include "smtpd.h" 42 #include "log.h" 43 44 #define SSL_CIPHERS "HIGH" 45 46 void ssl_error(const char *); 47 char *ssl_load_file(const char *, off_t *); 48 SSL_CTX *ssl_ctx_create(void); 49 void ssl_session_accept(int, short, void *); 50 void ssl_read(int, short, void *); 51 void ssl_write(int, short, void *); 52 int ssl_bufferevent_add(struct event *, int); 53 void ssl_connect(int, short, void *); 54 55 SSL *ssl_client_init(int, char *, size_t, char *, size_t); 56 57 int ssl_buf_read(SSL *, struct ibuf_read *); 58 int ssl_buf_write(SSL *, struct msgbuf *); 59 60 DH *get_dh1024(void); 61 DH *get_dh_from_memory(char *, size_t); 62 void ssl_set_ephemeral_key_exchange(SSL_CTX *, DH *); 63 64 extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, 65 size_t, void *); 66 67 void 68 ssl_connect(int fd, short event, void *p) 69 { 70 struct session *s = p; 71 int ret; 72 int retry_flag; 73 int ssl_err; 74 75 if (event == EV_TIMEOUT) { 76 log_debug("ssl_connect: session timed out"); 77 session_destroy(s); 78 return; 79 } 80 81 ret = SSL_connect(s->s_ssl); 82 if (ret <= 0) { 83 ssl_err = SSL_get_error(s->s_ssl, ret); 84 85 switch (ssl_err) { 86 case SSL_ERROR_WANT_READ: 87 retry_flag = EV_READ; 88 goto retry; 89 case SSL_ERROR_WANT_WRITE: 90 retry_flag = EV_WRITE; 91 goto retry; 92 case SSL_ERROR_ZERO_RETURN: 93 case SSL_ERROR_SYSCALL: 94 if (ret == 0) { 95 log_debug("session destroy in MTA #1"); 96 session_destroy(s); 97 return; 98 } 99 /* FALLTHROUGH */ 100 default: 101 ssl_error("ssl_session_connect"); 102 session_destroy(s); 103 return; 104 } 105 } 106 107 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 108 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 109 110 log_info("ssl_connect: connected to remote ssl server"); 111 bufferevent_enable(s->s_bev, EV_READ|EV_WRITE); 112 s->s_flags |= F_SECURE; 113 114 if (s->s_flags & F_PEERHASTLS) { 115 session_respond(s, "EHLO %s", env->sc_hostname); 116 } 117 118 return; 119 retry: 120 event_set(&s->s_ev, s->s_fd, EV_TIMEOUT|retry_flag, ssl_connect, s); 121 event_add(&s->s_ev, &s->s_tv); 122 } 123 124 void 125 ssl_read(int fd, short event, void *p) 126 { 127 struct bufferevent *bufev = p; 128 struct session *s = bufev->cbarg; 129 int ret; 130 int ssl_err; 131 short what; 132 size_t len; 133 char rbuf[IBUF_READ_SIZE]; 134 int howmuch = IBUF_READ_SIZE; 135 136 what = EVBUFFER_READ; 137 ret = ssl_err = 0; 138 139 if (event == EV_TIMEOUT) { 140 what |= EVBUFFER_TIMEOUT; 141 goto err; 142 } 143 144 if (bufev->wm_read.high != 0) 145 howmuch = MIN(sizeof(rbuf), bufev->wm_read.high); 146 147 ret = SSL_read(s->s_ssl, rbuf, howmuch); 148 if (ret <= 0) { 149 ssl_err = SSL_get_error(s->s_ssl, ret); 150 151 switch (ssl_err) { 152 case SSL_ERROR_WANT_READ: 153 goto retry; 154 case SSL_ERROR_WANT_WRITE: 155 goto retry; 156 default: 157 if (ret == 0) 158 what |= EVBUFFER_EOF; 159 else { 160 ssl_error("ssl_read"); 161 what |= EVBUFFER_ERROR; 162 } 163 goto err; 164 } 165 } 166 167 if (evbuffer_add(bufev->input, rbuf, ret) == -1) { 168 what |= EVBUFFER_ERROR; 169 goto err; 170 } 171 172 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 173 174 len = EVBUFFER_LENGTH(bufev->input); 175 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 176 return; 177 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { 178 struct evbuffer *buf = bufev->input; 179 event_del(&bufev->ev_read); 180 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 181 return; 182 } 183 184 if (bufev->readcb != NULL) 185 (*bufev->readcb)(bufev, bufev->cbarg); 186 return; 187 188 retry: 189 ssl_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 190 return; 191 192 err: 193 (*bufev->errorcb)(bufev, what, bufev->cbarg); 194 } 195 196 197 void 198 ssl_write(int fd, short event, void *p) 199 { 200 struct bufferevent *bufev = p; 201 struct session *s = bufev->cbarg; 202 int ret; 203 int ssl_err; 204 short what; 205 206 ret = 0; 207 what = EVBUFFER_WRITE; 208 209 if (event == EV_TIMEOUT) { 210 what |= EV_TIMEOUT; 211 goto err; 212 } 213 214 if (EVBUFFER_LENGTH(bufev->output)) { 215 if (s->s_buf == NULL) { 216 s->s_buflen = EVBUFFER_LENGTH(bufev->output); 217 if ((s->s_buf = malloc(s->s_buflen)) == NULL) { 218 what |= EVBUFFER_ERROR; 219 goto err; 220 } 221 memcpy(s->s_buf, EVBUFFER_DATA(bufev->output), 222 s->s_buflen); 223 } 224 225 ret = SSL_write(s->s_ssl, s->s_buf, s->s_buflen); 226 if (ret <= 0) { 227 ssl_err = SSL_get_error(s->s_ssl, ret); 228 229 switch (ssl_err) { 230 case SSL_ERROR_WANT_READ: 231 goto retry; 232 case SSL_ERROR_WANT_WRITE: 233 goto retry; 234 default: 235 if (ret == 0) 236 what |= EVBUFFER_EOF; 237 else { 238 ssl_error("ssl_write"); 239 what |= EVBUFFER_ERROR; 240 } 241 goto err; 242 } 243 } 244 evbuffer_drain(bufev->output, ret); 245 } 246 if (s->s_buf != NULL) { 247 free(s->s_buf); 248 s->s_buf = NULL; 249 s->s_buflen = 0; 250 } 251 if (EVBUFFER_LENGTH(bufev->output) != 0) 252 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 253 254 if (bufev->writecb != NULL && 255 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 256 (*bufev->writecb)(bufev, bufev->cbarg); 257 return; 258 259 retry: 260 if (s->s_buflen != 0) 261 ssl_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 262 return; 263 264 err: 265 if (s->s_buf != NULL) { 266 free(s->s_buf); 267 s->s_buf = NULL; 268 s->s_buflen = 0; 269 } 270 (*bufev->errorcb)(bufev, what, bufev->cbarg); 271 } 272 273 int 274 ssl_bufferevent_add(struct event *ev, int timeout) 275 { 276 struct timeval tv; 277 struct timeval *ptv = NULL; 278 279 if (timeout) { 280 timerclear(&tv); 281 tv.tv_sec = timeout; 282 ptv = &tv; 283 } 284 285 return (event_add(ev, ptv)); 286 } 287 288 int 289 ssl_cmp(struct ssl *s1, struct ssl *s2) 290 { 291 return (strcmp(s1->ssl_name, s2->ssl_name)); 292 } 293 294 SPLAY_GENERATE(ssltree, ssl, ssl_nodes, ssl_cmp); 295 296 char * 297 ssl_load_file(const char *name, off_t *len) 298 { 299 struct stat st; 300 off_t size; 301 char *buf = NULL; 302 int fd; 303 304 if ((fd = open(name, O_RDONLY)) == -1) 305 return (NULL); 306 if (fstat(fd, &st) != 0) 307 goto fail; 308 size = st.st_size; 309 if ((buf = calloc(1, size + 1)) == NULL) 310 goto fail; 311 if (read(fd, buf, size) != size) 312 goto fail; 313 close(fd); 314 315 *len = size + 1; 316 return (buf); 317 318 fail: 319 if (buf != NULL) 320 free(buf); 321 close(fd); 322 return (NULL); 323 } 324 325 SSL_CTX * 326 ssl_ctx_create(void) 327 { 328 SSL_CTX *ctx; 329 330 ctx = SSL_CTX_new(SSLv23_method()); 331 if (ctx == NULL) { 332 ssl_error("ssl_ctx_create"); 333 fatal("ssl_ctx_create: could not create SSL context"); 334 } 335 336 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 337 SSL_CTX_set_timeout(ctx, SMTPD_SESSION_TIMEOUT); 338 SSL_CTX_set_options(ctx, SSL_OP_ALL); 339 SSL_CTX_set_options(ctx, 340 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); 341 342 if (!SSL_CTX_set_cipher_list(ctx, SSL_CIPHERS)) { 343 ssl_error("ssl_ctx_create"); 344 fatal("ssl_ctx_create: could not set cipher list"); 345 } 346 return (ctx); 347 } 348 349 int 350 ssl_load_certfile(const char *name, u_int8_t flags) 351 { 352 struct ssl *s; 353 struct ssl key; 354 char certfile[PATH_MAX]; 355 356 if (strlcpy(key.ssl_name, name, sizeof(key.ssl_name)) 357 >= sizeof(key.ssl_name)) { 358 log_warn("ssl_load_certfile: certificate name truncated"); 359 return -1; 360 } 361 362 s = SPLAY_FIND(ssltree, env->sc_ssl, &key); 363 if (s != NULL) { 364 s->flags |= flags; 365 return 0; 366 } 367 368 if ((s = calloc(1, sizeof(*s))) == NULL) 369 fatal(NULL); 370 371 s->flags = flags; 372 (void)strlcpy(s->ssl_name, key.ssl_name, sizeof(s->ssl_name)); 373 374 if (! bsnprintf(certfile, sizeof(certfile), 375 "/etc/mail/certs/%s.crt", name)) 376 goto err; 377 378 if ((s->ssl_cert = ssl_load_file(certfile, &s->ssl_cert_len)) == NULL) 379 goto err; 380 381 if (! bsnprintf(certfile, sizeof(certfile), 382 "/etc/mail/certs/%s.key", name)) 383 goto err; 384 385 if ((s->ssl_key = ssl_load_file(certfile, &s->ssl_key_len)) == NULL) 386 goto err; 387 388 if (! bsnprintf(certfile, sizeof(certfile), 389 "/etc/mail/certs/%s.dh", name)) 390 goto err; 391 392 if ((s->ssl_dhparams = ssl_load_file(certfile, 393 &s->ssl_dhparams_len)) == NULL) { 394 log_info("no DH parameters found in %s", certfile); 395 log_info("using built-in DH parameters"); 396 } 397 398 SPLAY_INSERT(ssltree, env->sc_ssl, s); 399 400 return (0); 401 err: 402 if (s->ssl_cert != NULL) 403 free(s->ssl_cert); 404 if (s->ssl_key != NULL) 405 free(s->ssl_key); 406 if (s->ssl_dhparams != NULL) 407 free(s->ssl_dhparams); 408 if (s != NULL) 409 free(s); 410 return (-1); 411 } 412 413 void 414 ssl_init(void) 415 { 416 SSL_library_init(); 417 SSL_load_error_strings(); 418 419 OpenSSL_add_all_algorithms(); 420 421 /* Init hardware crypto engines. */ 422 ENGINE_load_builtin_engines(); 423 ENGINE_register_all_complete(); 424 } 425 426 void 427 ssl_setup(struct listener *l) 428 { 429 struct ssl key; 430 DH *dh; 431 432 if (!(l->flags & F_SSL)) 433 return; 434 435 if (strlcpy(key.ssl_name, l->ssl_cert_name, sizeof(key.ssl_name)) 436 >= sizeof(key.ssl_name)) 437 fatal("ssl_setup: certificate name truncated"); 438 439 if ((l->ssl = SPLAY_FIND(ssltree, env->sc_ssl, &key)) == NULL) 440 fatal("ssl_setup: certificate tree corrupted"); 441 442 l->ssl_ctx = ssl_ctx_create(); 443 444 if (!ssl_ctx_use_certificate_chain(l->ssl_ctx, 445 l->ssl->ssl_cert, l->ssl->ssl_cert_len)) 446 goto err; 447 if (!ssl_ctx_use_private_key(l->ssl_ctx, 448 l->ssl->ssl_key, l->ssl->ssl_key_len)) 449 goto err; 450 451 if (!SSL_CTX_check_private_key(l->ssl_ctx)) 452 goto err; 453 if (!SSL_CTX_set_session_id_context(l->ssl_ctx, 454 (const unsigned char *)l->ssl_cert_name, 455 strlen(l->ssl_cert_name) + 1)) 456 goto err; 457 458 459 460 if (l->ssl->ssl_dhparams_len == 0) 461 dh = get_dh1024(); 462 else 463 dh = get_dh_from_memory(l->ssl->ssl_dhparams, 464 l->ssl->ssl_dhparams_len); 465 ssl_set_ephemeral_key_exchange(l->ssl_ctx, dh); 466 467 log_debug("ssl_setup: ssl setup finished for listener: %p", l); 468 return; 469 470 err: 471 if (l->ssl_ctx != NULL) 472 SSL_CTX_free(l->ssl_ctx); 473 ssl_error("ssl_setup"); 474 fatal("ssl_setup: cannot set SSL up"); 475 return; 476 } 477 478 void 479 ssl_error(const char *where) 480 { 481 unsigned long code; 482 char errbuf[128]; 483 extern int debug; 484 485 if (!debug) 486 return; 487 for (; (code = ERR_get_error()) != 0 ;) { 488 ERR_error_string_n(code, errbuf, sizeof(errbuf)); 489 log_debug("SSL library error: %s: %s", where, errbuf); 490 } 491 } 492 493 void 494 ssl_session_accept(int fd, short event, void *p) 495 { 496 struct session *s = p; 497 int ret; 498 int retry_flag; 499 int ssl_err; 500 501 if (event == EV_TIMEOUT) { 502 log_debug("ssl_session_accept: session timed out"); 503 session_destroy(s); 504 return; 505 } 506 507 retry_flag = ssl_err = 0; 508 509 log_debug("ssl_session_accept: accepting client"); 510 ret = SSL_accept(s->s_ssl); 511 if (ret <= 0) { 512 ssl_err = SSL_get_error(s->s_ssl, ret); 513 514 switch (ssl_err) { 515 case SSL_ERROR_WANT_READ: 516 retry_flag = EV_READ; 517 goto retry; 518 case SSL_ERROR_WANT_WRITE: 519 retry_flag = EV_WRITE; 520 goto retry; 521 case SSL_ERROR_ZERO_RETURN: 522 case SSL_ERROR_SYSCALL: 523 if (ret == 0) { 524 session_destroy(s); 525 return; 526 } 527 /* FALLTHROUGH */ 528 default: 529 ssl_error("ssl_session_accept"); 530 session_destroy(s); 531 return; 532 } 533 } 534 535 536 log_info("ssl_session_accept: accepted ssl client"); 537 s->s_flags |= F_SECURE; 538 539 if (s->s_l->flags & F_SMTPS) 540 stat_increment(STATS_SMTP_SMTPS); 541 542 if (s->s_l->flags & F_STARTTLS) 543 stat_increment(STATS_SMTP_STARTTLS); 544 545 session_bufferevent_new(s); 546 event_set(&s->s_bev->ev_read, s->s_fd, EV_READ, ssl_read, s->s_bev); 547 event_set(&s->s_bev->ev_write, s->s_fd, EV_WRITE, ssl_write, s->s_bev); 548 session_pickup(s, NULL); 549 550 return; 551 retry: 552 event_add(&s->s_ev, &s->s_tv); 553 } 554 555 void 556 ssl_session_init(struct session *s) 557 { 558 struct listener *l; 559 SSL *ssl; 560 561 l = s->s_l; 562 563 if (!(l->flags & F_SSL)) 564 return; 565 566 log_debug("ssl_session_init: switching to SSL"); 567 ssl = SSL_new(l->ssl_ctx); 568 if (ssl == NULL) 569 goto err; 570 571 if (!SSL_set_ssl_method(ssl, SSLv23_server_method())) 572 goto err; 573 if (!SSL_set_fd(ssl, s->s_fd)) 574 goto err; 575 SSL_set_accept_state(ssl); 576 577 s->s_ssl = ssl; 578 579 s->s_tv.tv_sec = SMTPD_SESSION_TIMEOUT; 580 s->s_tv.tv_usec = 0; 581 event_set(&s->s_ev, s->s_fd, EV_READ|EV_TIMEOUT, ssl_session_accept, s); 582 event_add(&s->s_ev, &s->s_tv); 583 return; 584 585 err: 586 if (ssl != NULL) 587 SSL_free(ssl); 588 ssl_error("ssl_session_init"); 589 } 590 591 SSL * 592 ssl_client_init(int fd, char *cert, size_t certsz, char *key, size_t keysz) 593 { 594 SSL_CTX *ctx; 595 SSL *ssl = NULL; 596 int rv = -1; 597 598 ctx = ssl_ctx_create(); 599 600 if (cert && key) { 601 if (!ssl_ctx_use_certificate_chain(ctx, cert, certsz)) 602 goto done; 603 else if (!ssl_ctx_use_private_key(ctx, key, keysz)) 604 goto done; 605 else if (!SSL_CTX_check_private_key(ctx)) 606 goto done; 607 } 608 609 if ((ssl = SSL_new(ctx)) == NULL) 610 goto done; 611 612 if (!SSL_set_ssl_method(ssl, SSLv23_client_method())) 613 goto done; 614 if (!SSL_set_fd(ssl, fd)) 615 goto done; 616 SSL_set_connect_state(ssl); 617 618 rv = 0; 619 done: 620 if (rv) { 621 if (ssl) 622 SSL_free(ssl); 623 else if (ctx) 624 SSL_CTX_free(ctx); 625 ssl = NULL; 626 } 627 return (ssl); 628 } 629 630 void 631 ssl_session_destroy(struct session *s) 632 { 633 SSL_free(s->s_ssl); 634 635 if (s->s_l == NULL) { 636 /* called from mta */ 637 return; 638 } 639 640 if (s->s_l->flags & F_SMTPS) 641 if (s->s_flags & F_SECURE) 642 stat_decrement(STATS_SMTP_SMTPS); 643 644 if (s->s_l->flags & F_STARTTLS) 645 if (s->s_flags & F_SECURE) 646 stat_decrement(STATS_SMTP_STARTTLS); 647 } 648 649 int 650 ssl_buf_read(SSL *s, struct ibuf_read *r) 651 { 652 u_char *buf = r->buf + r->wpos; 653 ssize_t bufsz = sizeof(r->buf) - r->wpos; 654 int ret; 655 656 if (bufsz == 0) { 657 errno = EMSGSIZE; 658 return (SSL_ERROR_SYSCALL); 659 } 660 661 if ((ret = SSL_read(s, buf, bufsz)) > 0) 662 r->wpos += ret; 663 664 return SSL_get_error(s, ret); 665 } 666 667 int 668 ssl_buf_write(SSL *s, struct msgbuf *msgbuf) 669 { 670 struct ibuf *buf; 671 int ret; 672 673 buf = TAILQ_FIRST(&msgbuf->bufs); 674 if (buf == NULL) 675 return (SSL_ERROR_NONE); 676 677 ret = SSL_write(s, buf->buf + buf->rpos, buf->wpos - buf->rpos); 678 679 if (ret > 0) 680 msgbuf_drain(msgbuf, ret); 681 682 return SSL_get_error(s, ret); 683 } 684 685 /* From OpenSSL's documentation: 686 * 687 * If "strong" primes were used to generate the DH parameters, it is 688 * not strictly necessary to generate a new key for each handshake 689 * but it does improve forward secrecy. 690 * 691 * -- gilles@ 692 */ 693 DH * 694 get_dh1024(void) 695 { 696 DH *dh; 697 unsigned char dh1024_p[] = { 698 0xAD,0x37,0xBB,0x26,0x75,0x01,0x27,0x75, 699 0x06,0xB5,0xE7,0x1E,0x1F,0x2B,0xBC,0x51, 700 0xC0,0xF4,0xEB,0x42,0x7A,0x2A,0x83,0x1E, 701 0xE8,0xD1,0xD8,0xCC,0x9E,0xE6,0x15,0x1D, 702 0x06,0x46,0x50,0x94,0xB9,0xEE,0xB6,0x89, 703 0xB7,0x3C,0xAC,0x07,0x5E,0x29,0x37,0xCC, 704 0x8F,0xDF,0x48,0x56,0x85,0x83,0x26,0x02, 705 0xB8,0xB6,0x63,0xAF,0x2D,0x4A,0x57,0x93, 706 0x6B,0x54,0xE1,0x8F,0x28,0x76,0x9C,0x5D, 707 0x90,0x65,0xD1,0x07,0xFE,0x5B,0x05,0x65, 708 0xDA,0xD2,0xE2,0xAF,0x23,0xCA,0x2F,0xD6, 709 0x4B,0xD2,0x04,0xFE,0xDF,0x21,0x2A,0xE1, 710 0xCD,0x1B,0x70,0x76,0xB3,0x51,0xA4,0xC9, 711 0x2B,0x68,0xE3,0xDD,0xCB,0x97,0xDA,0x59, 712 0x50,0x93,0xEE,0xDB,0xBF,0xC7,0xFA,0xA7, 713 0x47,0xC4,0x4D,0xF0,0xC6,0x09,0x4A,0x4B 714 }; 715 unsigned char dh1024_g[] = { 716 0x02 717 }; 718 719 if ((dh = DH_new()) == NULL) 720 return NULL; 721 722 dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); 723 dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); 724 if (dh->p == NULL || dh->g == NULL) { 725 DH_free(dh); 726 return NULL; 727 } 728 729 return dh; 730 } 731 732 DH * 733 get_dh_from_memory(char *params, size_t len) 734 { 735 BIO *mem; 736 DH *dh; 737 738 mem = BIO_new_mem_buf(params, len); 739 if (mem == NULL) 740 return NULL; 741 dh = PEM_read_bio_DHparams(mem, NULL, NULL, NULL); 742 if (dh == NULL) 743 goto err; 744 if (dh->p == NULL || dh->g == NULL) 745 goto err; 746 return dh; 747 748 err: 749 if (mem != NULL) 750 BIO_free(mem); 751 if (dh != NULL) 752 DH_free(dh); 753 return NULL; 754 } 755 756 757 void 758 ssl_set_ephemeral_key_exchange(SSL_CTX *ctx, DH *dh) 759 { 760 if (dh == NULL || !SSL_CTX_set_tmp_dh(ctx, dh)) { 761 ssl_error("ssl_set_ephemeral_key_exchange"); 762 fatal("ssl_set_ephemeral_key_exchange: cannot set tmp dh"); 763 } 764 } 765