Merge remote-tracking branch 'origin/vendor/BINUTILS227'
[dragonfly.git] / crypto / libressl / tls / tls_server.c
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 }