xref: /dragonfly/crypto/libressl/tls/tls_server.c (revision f5b1c8a1)
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