Update libressl README.DRAGONFLY for v2.4.4
[dragonfly.git] / crypto / libressl / tls / tls_server.c
CommitLineData
f5b1c8a1
JM
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
25struct tls *
26tls_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
38struct tls *
39tls_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
51int
52tls_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
113int
114tls_accept_socket(struct tls *ctx, struct tls **cctx, int socket)
115{
116 return (tls_accept_fds(ctx, cctx, socket, socket));
117}
118
119int
120tls_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
160int
161tls_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}