xref: /openbsd-src/lib/libtls/tls_server.c (revision 5b859c19fe53bbea08f5c342e0a4470e99f883e1)
1 /* $OpenBSD: tls_server.c,v 1.1 2014/10/31 13:46:17 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 
55 	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
56 		tls_set_error(ctx, "ssl context failure");
57 		goto err;
58 	}
59 
60 	if (tls_configure_ssl(ctx) != 0)
61 		goto err;
62 	if (tls_configure_keypair(ctx) != 0)
63 		goto err;
64 
65 	if (ctx->config->ecdhcurve == -1) {
66 		SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
67 	} else if (ctx->config->ecdhcurve != NID_undef) {
68 		if ((ecdh_key = EC_KEY_new_by_curve_name(
69 		    ctx->config->ecdhcurve)) == NULL) {
70 			tls_set_error(ctx, "failed to set ECDH curve");
71 			goto err;
72 		}
73 		SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
74 		SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ecdh_key);
75 		EC_KEY_free(ecdh_key);
76 	}
77 
78 	return (0);
79 
80 err:
81 	return (-1);
82 }
83 
84 int
85 tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket)
86 {
87 	struct tls *conn_ctx = *cctx;
88 	int ret, ssl_err;
89 
90 	if ((ctx->flags & TLS_SERVER) == 0) {
91 		tls_set_error(ctx, "not a server context");
92 		goto err;
93 	}
94 
95 	if (conn_ctx == NULL) {
96 		if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
97 			tls_set_error(ctx, "connection context failure");
98 			goto err;
99 		}
100 		*cctx = conn_ctx;
101 
102 		conn_ctx->socket = socket;
103 
104 		if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
105 			tls_set_error(ctx, "ssl failure");
106 			goto err;
107 		}
108 
109 		if (SSL_set_fd(conn_ctx->ssl_conn, socket) != 1) {
110 			tls_set_error(ctx, "ssl set fd failure");
111 			goto err;
112 		}
113 		SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx);
114 	}
115 
116 	if ((ret = SSL_accept(conn_ctx->ssl_conn)) != 1) {
117 		ssl_err = SSL_get_error(conn_ctx->ssl_conn, ret);
118 		switch (ssl_err) {
119 		case SSL_ERROR_WANT_READ:
120 			return (TLS_READ_AGAIN);
121 		case SSL_ERROR_WANT_WRITE:
122 			return (TLS_WRITE_AGAIN);
123 		default:
124 			tls_set_error(ctx, "ssl accept failure (%i)",
125 			    ssl_err);
126 			goto err;
127 		}
128 	}
129 
130 	return (0);
131 
132 err:
133 	return (-1);
134 }
135