1 /* $OpenBSD: tls_server.c,v 1.18 2015/09/29 10:17:04 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/ec.h> 19 #include <openssl/err.h> 20 #include <openssl/ssl.h> 21 22 #include <tls.h> 23 #include "tls_internal.h" 24 25 struct tls * 26 tls_server(void) 27 { 28 struct tls *ctx; 29 30 if ((ctx = tls_new()) == NULL) 31 return (NULL); 32 33 ctx->flags |= TLS_SERVER; 34 35 return (ctx); 36 } 37 38 struct tls * 39 tls_server_conn(struct tls *ctx) 40 { 41 struct tls *conn_ctx; 42 43 if ((conn_ctx = tls_new()) == NULL) 44 return (NULL); 45 46 conn_ctx->flags |= TLS_SERVER_CONN; 47 48 return (conn_ctx); 49 } 50 51 int 52 tls_configure_server(struct tls *ctx) 53 { 54 EC_KEY *ecdh_key; 55 unsigned char sid[SSL_MAX_SSL_SESSION_ID_LENGTH]; 56 57 if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { 58 tls_set_errorx(ctx, "ssl context failure"); 59 goto err; 60 } 61 62 if (tls_configure_ssl(ctx) != 0) 63 goto err; 64 if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 1) != 0) 65 goto err; 66 if (ctx->config->verify_client != 0) { 67 int verify = SSL_VERIFY_PEER; 68 if (ctx->config->verify_client == 1) 69 verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 70 if (tls_configure_ssl_verify(ctx, verify) == -1) 71 goto err; 72 } 73 74 if (ctx->config->dheparams == -1) 75 SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1); 76 else if (ctx->config->dheparams == 1024) 77 SSL_CTX_set_dh_auto(ctx->ssl_ctx, 2); 78 79 if (ctx->config->ecdhecurve == -1) { 80 SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1); 81 } else if (ctx->config->ecdhecurve != NID_undef) { 82 if ((ecdh_key = EC_KEY_new_by_curve_name( 83 ctx->config->ecdhecurve)) == NULL) { 84 tls_set_errorx(ctx, "failed to set ECDHE curve"); 85 goto err; 86 } 87 SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); 88 SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ecdh_key); 89 EC_KEY_free(ecdh_key); 90 } 91 92 if (ctx->config->ciphers_server == 1) 93 SSL_CTX_set_options(ctx->ssl_ctx, 94 SSL_OP_CIPHER_SERVER_PREFERENCE); 95 96 /* 97 * Set session ID context to a random value. We don't support 98 * persistent caching of sessions so it is OK to set a temporary 99 * session ID context that is valid during run time. 100 */ 101 arc4random_buf(sid, sizeof(sid)); 102 if (!SSL_CTX_set_session_id_context(ctx->ssl_ctx, sid, sizeof(sid))) { 103 tls_set_errorx(ctx, "failed to set session id context"); 104 goto err; 105 } 106 107 return (0); 108 109 err: 110 return (-1); 111 } 112 113 int 114 tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket) 115 { 116 return (tls_accept_fds(ctx, cctx, socket, socket)); 117 } 118 119 int 120 tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) 121 { 122 struct tls *conn_ctx = NULL; 123 124 if ((ctx->flags & TLS_SERVER) == 0) { 125 tls_set_errorx(ctx, "not a server context"); 126 goto err; 127 } 128 129 if ((conn_ctx = tls_server_conn(ctx)) == NULL) { 130 tls_set_errorx(ctx, "connection context failure"); 131 goto err; 132 } 133 134 if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { 135 tls_set_errorx(ctx, "ssl failure"); 136 goto err; 137 } 138 if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { 139 tls_set_errorx(ctx, "ssl application data failure"); 140 goto err; 141 } 142 if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || 143 SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { 144 tls_set_errorx(ctx, "ssl file descriptor failure"); 145 goto err; 146 } 147 148 *cctx = conn_ctx; 149 150 return (0); 151 152 err: 153 tls_free(conn_ctx); 154 155 *cctx = NULL; 156 157 return (-1); 158 } 159 160 int 161 tls_handshake_server(struct tls *ctx) 162 { 163 int ssl_ret; 164 int rv = -1; 165 166 if ((ctx->flags & TLS_SERVER_CONN) == 0) { 167 tls_set_errorx(ctx, "not a server connection context"); 168 goto err; 169 } 170 171 ERR_clear_error(); 172 if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) { 173 rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); 174 goto err; 175 } 176 177 ctx->state |= TLS_HANDSHAKE_COMPLETE; 178 rv = 0; 179 180 err: 181 return (rv); 182 } 183