xref: /openbsd-src/lib/libtls/tls_server.c (revision 240d3da60be716cf2fce1465b5051e707ecce5cc)
1 /* $OpenBSD: tls_server.c,v 1.13 2015/09/09 19:49:07 jsing 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/ssl.h>
20 
21 #include <tls.h>
22 #include "tls_internal.h"
23 
24 struct tls *
25 tls_server(void)
26 {
27 	struct tls *ctx;
28 
29 	if ((ctx = tls_new()) == NULL)
30 		return (NULL);
31 
32 	ctx->flags |= TLS_SERVER;
33 
34 	return (ctx);
35 }
36 
37 struct tls *
38 tls_server_conn(struct tls *ctx)
39 {
40 	struct tls *conn_ctx;
41 
42 	if ((conn_ctx = tls_new()) == NULL)
43 		return (NULL);
44 
45 	conn_ctx->flags |= TLS_SERVER_CONN;
46 
47 	return (conn_ctx);
48 }
49 
50 int
51 tls_configure_server(struct tls *ctx)
52 {
53 	EC_KEY *ecdh_key;
54 	unsigned char sid[SSL_MAX_SSL_SESSION_ID_LENGTH];
55 
56 	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
57 		tls_set_errorx(ctx, "ssl context failure");
58 		goto err;
59 	}
60 
61 	if (tls_configure_ssl(ctx) != 0)
62 		goto err;
63 	if (tls_configure_keypair(ctx, 1) != 0)
64 		goto err;
65 	if (ctx->config->verify_client != 0) {
66 		int verify = SSL_VERIFY_PEER;
67 		if (ctx->config->verify_client == 1)
68 			verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
69 		if (tls_configure_ssl_verify(ctx, verify) == -1)
70 			goto err;
71 	}
72 
73 	if (ctx->config->dheparams == -1)
74 		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1);
75 	else if (ctx->config->dheparams == 1024)
76 		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 2);
77 
78 	if (ctx->config->ecdhecurve == -1) {
79 		SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
80 	} else if (ctx->config->ecdhecurve != NID_undef) {
81 		if ((ecdh_key = EC_KEY_new_by_curve_name(
82 		    ctx->config->ecdhecurve)) == NULL) {
83 			tls_set_errorx(ctx, "failed to set ECDHE curve");
84 			goto err;
85 		}
86 		SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
87 		SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ecdh_key);
88 		EC_KEY_free(ecdh_key);
89 	}
90 
91 	/*
92 	 * Set session ID context to a random value.  We don't support
93 	 * persistent caching of sessions so it is OK to set a temporary
94 	 * session ID context that is valid during run time.
95 	 */
96 	arc4random_buf(sid, sizeof(sid));
97 	if (!SSL_CTX_set_session_id_context(ctx->ssl_ctx, sid, sizeof(sid))) {
98 		tls_set_errorx(ctx, "failed to set session id context");
99 		goto err;
100 	}
101 
102 	return (0);
103 
104  err:
105 	return (-1);
106 }
107 
108 int
109 tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
110 {
111 	struct tls *conn_ctx = *cctx;
112 	int ret, err;
113 
114 	if ((ctx->flags & TLS_SERVER) == 0) {
115 		tls_set_errorx(ctx, "not a server context");
116 		goto err;
117 	}
118 
119 	if (conn_ctx == NULL) {
120 		if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
121 			tls_set_errorx(ctx, "connection context failure");
122 			goto err;
123 		}
124 		*cctx = conn_ctx;
125 
126 		if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
127 			tls_set_errorx(ctx, "ssl failure");
128 			goto err;
129 		}
130 		if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) {
131 			tls_set_errorx(ctx, "ssl application data failure");
132 			goto err;
133 		}
134 		if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
135 		    SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
136 			tls_set_errorx(ctx, "ssl file descriptor failure");
137 			goto err;
138 		}
139 	}
140 
141 	if ((ret = SSL_accept(conn_ctx->ssl_conn)) != 1) {
142 		err = tls_ssl_error(ctx, conn_ctx->ssl_conn, ret, "accept");
143 		if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) {
144 			return (err);
145 		}
146 		goto err;
147 	}
148 
149 	return (0);
150 
151  err:
152 	return (-1);
153 }
154 
155 int
156 tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket)
157 {
158 	return (tls_accept_fds(ctx, cctx, socket, socket));
159 }
160