1*40ae7d6bSjoshua /* $OpenBSD: tls_server.c,v 1.51 2024/03/26 08:54:48 joshua Exp $ */
2b600beedSjsing /*
3b600beedSjsing * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4b600beedSjsing *
5b600beedSjsing * Permission to use, copy, modify, and distribute this software for any
6b600beedSjsing * purpose with or without fee is hereby granted, provided that the above
7b600beedSjsing * copyright notice and this permission notice appear in all copies.
8b600beedSjsing *
9b600beedSjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10b600beedSjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11b600beedSjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12b600beedSjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13b600beedSjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14b600beedSjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15b600beedSjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16b600beedSjsing */
17b600beedSjsing
18f89edc01Sjsing #include <sys/socket.h>
19f89edc01Sjsing
20f89edc01Sjsing #include <arpa/inet.h>
21f89edc01Sjsing
22e6d77be9Sop #include <string.h>
23e6d77be9Sop
24b600beedSjsing #include <openssl/ec.h>
259ba095aaSjsing #include <openssl/err.h>
26b600beedSjsing #include <openssl/ssl.h>
27b600beedSjsing
28b600beedSjsing #include <tls.h>
29b600beedSjsing #include "tls_internal.h"
30b600beedSjsing
31b600beedSjsing struct tls *
tls_server(void)32b600beedSjsing tls_server(void)
33b600beedSjsing {
34b600beedSjsing struct tls *ctx;
35b600beedSjsing
36b9573a74Sjsing if (tls_init() == -1)
37b9573a74Sjsing return (NULL);
38b9573a74Sjsing
39b600beedSjsing if ((ctx = tls_new()) == NULL)
40b600beedSjsing return (NULL);
41b600beedSjsing
42b600beedSjsing ctx->flags |= TLS_SERVER;
43b600beedSjsing
44b600beedSjsing return (ctx);
45b600beedSjsing }
46b600beedSjsing
47b600beedSjsing struct tls *
tls_server_conn(struct tls * ctx)48b600beedSjsing tls_server_conn(struct tls *ctx)
49b600beedSjsing {
50b600beedSjsing struct tls *conn_ctx;
51b600beedSjsing
52b600beedSjsing if ((conn_ctx = tls_new()) == NULL)
53b600beedSjsing return (NULL);
54b600beedSjsing
55b600beedSjsing conn_ctx->flags |= TLS_SERVER_CONN;
5688c10dabSjsing
57565eed69Sbcook pthread_mutex_lock(&ctx->config->mutex);
5888c10dabSjsing ctx->config->refcount++;
59565eed69Sbcook pthread_mutex_unlock(&ctx->config->mutex);
609ee433b9Sjsing
61668bec95Sbeck conn_ctx->config = ctx->config;
629ee433b9Sjsing conn_ctx->keypair = ctx->config->keypair;
63b600beedSjsing
64b600beedSjsing return (conn_ctx);
65b600beedSjsing }
66b600beedSjsing
67183da8c6Sjsing static int
tls_server_alpn_cb(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)68183da8c6Sjsing tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
69183da8c6Sjsing const unsigned char *in, unsigned int inlen, void *arg)
70183da8c6Sjsing {
71183da8c6Sjsing struct tls *ctx = arg;
72183da8c6Sjsing
73183da8c6Sjsing if (SSL_select_next_proto((unsigned char**)out, outlen,
74183da8c6Sjsing ctx->config->alpn, ctx->config->alpn_len, in, inlen) ==
75183da8c6Sjsing OPENSSL_NPN_NEGOTIATED)
76183da8c6Sjsing return (SSL_TLSEXT_ERR_OK);
77183da8c6Sjsing
78183da8c6Sjsing return (SSL_TLSEXT_ERR_NOACK);
79183da8c6Sjsing }
80183da8c6Sjsing
81991d42a1Sjsing static int
tls_servername_cb(SSL * ssl,int * al,void * arg)82f89edc01Sjsing tls_servername_cb(SSL *ssl, int *al, void *arg)
83f89edc01Sjsing {
84f89edc01Sjsing struct tls *ctx = (struct tls *)arg;
85f89edc01Sjsing struct tls_sni_ctx *sni_ctx;
86f89edc01Sjsing union tls_addr addrbuf;
87f89edc01Sjsing struct tls *conn_ctx;
88f89edc01Sjsing const char *name;
895f3c5205Sjsing int match;
90f89edc01Sjsing
91f89edc01Sjsing if ((conn_ctx = SSL_get_app_data(ssl)) == NULL)
92f89edc01Sjsing goto err;
93f89edc01Sjsing
945f3c5205Sjsing if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) ==
955f3c5205Sjsing NULL) {
96f89edc01Sjsing /*
97f89edc01Sjsing * The servername callback gets called even when there is no
98f89edc01Sjsing * TLS servername extension provided by the client. Sigh!
99f89edc01Sjsing */
100f89edc01Sjsing return (SSL_TLSEXT_ERR_NOACK);
101f89edc01Sjsing }
102f89edc01Sjsing
103dd391ab5Sjsing /*
104dd391ab5Sjsing * Per RFC 6066 section 3: ensure that name is not an IP literal.
105dd391ab5Sjsing *
106dd391ab5Sjsing * While we should treat this as an error, a number of clients
107dd391ab5Sjsing * (Python, Ruby and Safari) are not RFC compliant. To avoid handshake
108dd391ab5Sjsing * failures, pretend that we did not receive the extension.
109dd391ab5Sjsing */
110f89edc01Sjsing if (inet_pton(AF_INET, name, &addrbuf) == 1 ||
111f89edc01Sjsing inet_pton(AF_INET6, name, &addrbuf) == 1)
112dd391ab5Sjsing return (SSL_TLSEXT_ERR_NOACK);
113f89edc01Sjsing
11409626e4bStb free(conn_ctx->servername);
115f89edc01Sjsing if ((conn_ctx->servername = strdup(name)) == NULL)
116f89edc01Sjsing goto err;
117f89edc01Sjsing
118f89edc01Sjsing /* Find appropriate SSL context for requested servername. */
119f89edc01Sjsing for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) {
1205f3c5205Sjsing if (tls_check_name(ctx, sni_ctx->ssl_cert, name,
1215f3c5205Sjsing &match) == -1)
1225f3c5205Sjsing goto err;
1235f3c5205Sjsing if (match) {
1249ee433b9Sjsing conn_ctx->keypair = sni_ctx->keypair;
125f89edc01Sjsing SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx);
126f89edc01Sjsing return (SSL_TLSEXT_ERR_OK);
127f89edc01Sjsing }
128f89edc01Sjsing }
129f89edc01Sjsing
130f89edc01Sjsing /* No match, use the existing context/certificate. */
131f89edc01Sjsing return (SSL_TLSEXT_ERR_OK);
132f89edc01Sjsing
133f89edc01Sjsing err:
134f89edc01Sjsing /*
135f89edc01Sjsing * There is no way to tell libssl that an internal failure occurred.
136f89edc01Sjsing * The only option we have is to return a fatal alert.
137f89edc01Sjsing */
13879d77232Stb *al = SSL_AD_INTERNAL_ERROR;
139f89edc01Sjsing return (SSL_TLSEXT_ERR_ALERT_FATAL);
140f89edc01Sjsing }
141f89edc01Sjsing
14247c43cfeSclaudio static struct tls_ticket_key *
tls_server_ticket_key(struct tls_config * config,unsigned char * keyname)14347c43cfeSclaudio tls_server_ticket_key(struct tls_config *config, unsigned char *keyname)
14447c43cfeSclaudio {
14547c43cfeSclaudio struct tls_ticket_key *key = NULL;
14647c43cfeSclaudio time_t now;
14747c43cfeSclaudio int i;
14847c43cfeSclaudio
14947c43cfeSclaudio now = time(NULL);
15047c43cfeSclaudio if (config->ticket_autorekey == 1) {
15147c43cfeSclaudio if (now - 3 * (config->session_lifetime / 4) >
15247c43cfeSclaudio config->ticket_keys[0].time) {
15347c43cfeSclaudio if (tls_config_ticket_autorekey(config) == -1)
15447c43cfeSclaudio return (NULL);
15547c43cfeSclaudio }
15647c43cfeSclaudio }
15747c43cfeSclaudio for (i = 0; i < TLS_NUM_TICKETS; i++) {
15847c43cfeSclaudio struct tls_ticket_key *tk = &config->ticket_keys[i];
15947c43cfeSclaudio if (now - config->session_lifetime > tk->time)
16047c43cfeSclaudio continue;
16147c43cfeSclaudio if (keyname == NULL || timingsafe_memcmp(keyname,
16247c43cfeSclaudio tk->key_name, sizeof(tk->key_name)) == 0) {
16347c43cfeSclaudio key = tk;
16447c43cfeSclaudio break;
16547c43cfeSclaudio }
16647c43cfeSclaudio }
16747c43cfeSclaudio return (key);
16847c43cfeSclaudio }
16947c43cfeSclaudio
17047c43cfeSclaudio static int
tls_server_ticket_cb(SSL * ssl,unsigned char * keyname,unsigned char * iv,EVP_CIPHER_CTX * ctx,HMAC_CTX * hctx,int mode)17147c43cfeSclaudio tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv,
17247c43cfeSclaudio EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode)
17347c43cfeSclaudio {
17447c43cfeSclaudio struct tls_ticket_key *key;
17547c43cfeSclaudio struct tls *tls_ctx;
17647c43cfeSclaudio
17747c43cfeSclaudio if ((tls_ctx = SSL_get_app_data(ssl)) == NULL)
17847c43cfeSclaudio return (-1);
17947c43cfeSclaudio
18047c43cfeSclaudio if (mode == 1) {
18147c43cfeSclaudio /* create new session */
18247c43cfeSclaudio key = tls_server_ticket_key(tls_ctx->config, NULL);
18347c43cfeSclaudio if (key == NULL) {
1847a756d37Sjoshua tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN,
1857a756d37Sjoshua "no valid ticket key found");
18647c43cfeSclaudio return (-1);
18747c43cfeSclaudio }
18847c43cfeSclaudio
18947c43cfeSclaudio memcpy(keyname, key->key_name, sizeof(key->key_name));
19047c43cfeSclaudio arc4random_buf(iv, EVP_MAX_IV_LENGTH);
191bcc534f9Sinoguchi if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
192bcc534f9Sinoguchi key->aes_key, iv)) {
1937a756d37Sjoshua tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN,
1947a756d37Sjoshua "failed to init encrypt");
195bcc534f9Sinoguchi return (-1);
196bcc534f9Sinoguchi }
197bcc534f9Sinoguchi if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
198bcc534f9Sinoguchi EVP_sha256(), NULL)) {
1997a756d37Sjoshua tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN,
2007a756d37Sjoshua "failed to init hmac");
201bcc534f9Sinoguchi return (-1);
202bcc534f9Sinoguchi }
20347c43cfeSclaudio return (0);
20447c43cfeSclaudio } else {
20547c43cfeSclaudio /* get key by name */
20647c43cfeSclaudio key = tls_server_ticket_key(tls_ctx->config, keyname);
20747c43cfeSclaudio if (key == NULL)
20847c43cfeSclaudio return (0);
20947c43cfeSclaudio
210bcc534f9Sinoguchi if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
211bcc534f9Sinoguchi key->aes_key, iv)) {
2127a756d37Sjoshua tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN,
2137a756d37Sjoshua "failed to init decrypt");
214bcc534f9Sinoguchi return (-1);
215bcc534f9Sinoguchi }
216bcc534f9Sinoguchi if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
217bcc534f9Sinoguchi EVP_sha256(), NULL)) {
2187a756d37Sjoshua tls_set_errorx(tls_ctx, TLS_ERROR_UNKNOWN,
2197a756d37Sjoshua "failed to init hmac");
220bcc534f9Sinoguchi return (-1);
221bcc534f9Sinoguchi }
22247c43cfeSclaudio
22347c43cfeSclaudio /* time to renew the ticket? is it the primary key? */
22447c43cfeSclaudio if (key != &tls_ctx->config->ticket_keys[0])
22547c43cfeSclaudio return (2);
22647c43cfeSclaudio return (1);
22747c43cfeSclaudio }
22847c43cfeSclaudio }
22947c43cfeSclaudio
230f89edc01Sjsing static int
tls_configure_server_ssl(struct tls * ctx,SSL_CTX ** ssl_ctx,struct tls_keypair * keypair)231991d42a1Sjsing tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx,
232991d42a1Sjsing struct tls_keypair *keypair)
233b600beedSjsing {
234991d42a1Sjsing SSL_CTX_free(*ssl_ctx);
235991d42a1Sjsing
236991d42a1Sjsing if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
2377a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl context failure");
238b600beedSjsing goto err;
239b600beedSjsing }
240b600beedSjsing
241f61da50dSjsing SSL_CTX_set_options(*ssl_ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
242f61da50dSjsing
243f89edc01Sjsing if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx,
244f89edc01Sjsing tls_servername_cb) != 1) {
2457a756d37Sjoshua tls_set_error(ctx, TLS_ERROR_UNKNOWN,
2467a756d37Sjoshua "failed to set servername callback");
247f89edc01Sjsing goto err;
248f89edc01Sjsing }
249f89edc01Sjsing if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) {
2507a756d37Sjoshua tls_set_error(ctx, TLS_ERROR_UNKNOWN,
2517a756d37Sjoshua "failed to set servername callback arg");
252f89edc01Sjsing goto err;
253f89edc01Sjsing }
254f89edc01Sjsing
255991d42a1Sjsing if (tls_configure_ssl(ctx, *ssl_ctx) != 0)
256b600beedSjsing goto err;
257991d42a1Sjsing if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0)
258b600beedSjsing goto err;
25951f3bd3dSbeck if (ctx->config->verify_client != 0) {
26051f3bd3dSbeck int verify = SSL_VERIFY_PEER;
26151f3bd3dSbeck if (ctx->config->verify_client == 1)
26251f3bd3dSbeck verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
263991d42a1Sjsing if (tls_configure_ssl_verify(ctx, *ssl_ctx, verify) == -1)
26451f3bd3dSbeck goto err;
26551f3bd3dSbeck }
266b600beedSjsing
267183da8c6Sjsing if (ctx->config->alpn != NULL)
268991d42a1Sjsing SSL_CTX_set_alpn_select_cb(*ssl_ctx, tls_server_alpn_cb,
269183da8c6Sjsing ctx);
270183da8c6Sjsing
2719e5deb48Sjsing if (ctx->config->dheparams == -1)
272991d42a1Sjsing SSL_CTX_set_dh_auto(*ssl_ctx, 1);
2739e5deb48Sjsing else if (ctx->config->dheparams == 1024)
274991d42a1Sjsing SSL_CTX_set_dh_auto(*ssl_ctx, 2);
2759e5deb48Sjsing
2764896de1eSjsing if (ctx->config->ecdhecurves != NULL) {
277991d42a1Sjsing SSL_CTX_set_ecdh_auto(*ssl_ctx, 1);
2784896de1eSjsing if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves,
2794896de1eSjsing ctx->config->ecdhecurves_len) != 1) {
2807a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
2817a756d37Sjoshua "failed to set ecdhe curves");
282b600beedSjsing goto err;
283b600beedSjsing }
284b600beedSjsing }
285b600beedSjsing
286c57e6ec0Sjsing if (ctx->config->ciphers_server == 1)
287991d42a1Sjsing SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
288c57e6ec0Sjsing
2892279ffc3Sbeck if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) {
2907a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
2917a756d37Sjoshua "failed to add OCSP stapling callback");
292668bec95Sbeck goto err;
293668bec95Sbeck }
294668bec95Sbeck
29547c43cfeSclaudio if (ctx->config->session_lifetime > 0) {
29647c43cfeSclaudio /* set the session lifetime and enable tickets */
29747c43cfeSclaudio SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime);
29847c43cfeSclaudio SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET);
29947c43cfeSclaudio if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx,
30047c43cfeSclaudio tls_server_ticket_cb)) {
3017a756d37Sjoshua tls_set_error(ctx, TLS_ERROR_UNKNOWN,
30247c43cfeSclaudio "failed to set the TLS ticket callback");
30347c43cfeSclaudio goto err;
30447c43cfeSclaudio }
30547c43cfeSclaudio }
30647c43cfeSclaudio
30747c43cfeSclaudio if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id,
30847c43cfeSclaudio sizeof(ctx->config->session_id)) != 1) {
3097a756d37Sjoshua tls_set_error(ctx, TLS_ERROR_UNKNOWN,
3107a756d37Sjoshua "failed to set session id context");
31131413d7eSreyk goto err;
31231413d7eSreyk }
31331413d7eSreyk
314b600beedSjsing return (0);
315b600beedSjsing
316b600beedSjsing err:
317991d42a1Sjsing SSL_CTX_free(*ssl_ctx);
318991d42a1Sjsing *ssl_ctx = NULL;
319991d42a1Sjsing
320991d42a1Sjsing return (-1);
321991d42a1Sjsing }
322991d42a1Sjsing
323f89edc01Sjsing static int
tls_configure_server_sni(struct tls * ctx)324f89edc01Sjsing tls_configure_server_sni(struct tls *ctx)
325f89edc01Sjsing {
326f89edc01Sjsing struct tls_sni_ctx **sni_ctx;
327f89edc01Sjsing struct tls_keypair *kp;
328f89edc01Sjsing
329f89edc01Sjsing if (ctx->config->keypair->next == NULL)
330f89edc01Sjsing return (0);
331f89edc01Sjsing
332f89edc01Sjsing /* Set up additional SSL contexts for SNI. */
333f89edc01Sjsing sni_ctx = &ctx->sni_ctx;
334f89edc01Sjsing for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) {
335f89edc01Sjsing if ((*sni_ctx = tls_sni_ctx_new()) == NULL) {
3367a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_OUT_OF_MEMORY, "out of memory");
337f89edc01Sjsing goto err;
338f89edc01Sjsing }
3399ee433b9Sjsing (*sni_ctx)->keypair = kp;
340f89edc01Sjsing if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1)
341f89edc01Sjsing goto err;
342f89edc01Sjsing if (tls_keypair_load_cert(kp, &ctx->error,
343f89edc01Sjsing &(*sni_ctx)->ssl_cert) == -1)
344f89edc01Sjsing goto err;
345f89edc01Sjsing sni_ctx = &(*sni_ctx)->next;
346f89edc01Sjsing }
347f89edc01Sjsing
348f89edc01Sjsing return (0);
349f89edc01Sjsing
350f89edc01Sjsing err:
351f89edc01Sjsing return (-1);
352f89edc01Sjsing }
353f89edc01Sjsing
354991d42a1Sjsing int
tls_configure_server(struct tls * ctx)355991d42a1Sjsing tls_configure_server(struct tls *ctx)
356991d42a1Sjsing {
357991d42a1Sjsing if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx,
358991d42a1Sjsing ctx->config->keypair) == -1)
359991d42a1Sjsing goto err;
360f89edc01Sjsing if (tls_configure_server_sni(ctx) == -1)
361f89edc01Sjsing goto err;
362991d42a1Sjsing
363991d42a1Sjsing return (0);
364991d42a1Sjsing
365991d42a1Sjsing err:
366b600beedSjsing return (-1);
367b600beedSjsing }
368b600beedSjsing
369ed19021fSbcook static struct tls *
tls_accept_common(struct tls * ctx)3702233a86cSjsing tls_accept_common(struct tls *ctx)
371b600beedSjsing {
372e2b71c11Sjsing struct tls *conn_ctx = NULL;
373b600beedSjsing
374b600beedSjsing if ((ctx->flags & TLS_SERVER) == 0) {
375*40ae7d6bSjoshua tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT,
376*40ae7d6bSjoshua "not a server context");
377b600beedSjsing goto err;
378b600beedSjsing }
379b600beedSjsing
380b600beedSjsing if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
3817a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
3827a756d37Sjoshua "connection context failure");
383b600beedSjsing goto err;
384b600beedSjsing }
385b600beedSjsing
386b600beedSjsing if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
3877a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "ssl failure");
388b600beedSjsing goto err;
389b600beedSjsing }
390ed19021fSbcook
3918c73da28Sjsing if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) {
3927a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
3937a756d37Sjoshua "ssl application data failure");
3948c73da28Sjsing goto err;
3958c73da28Sjsing }
396ed19021fSbcook
397ed19021fSbcook return conn_ctx;
398ed19021fSbcook
399ed19021fSbcook err:
400ed19021fSbcook tls_free(conn_ctx);
401ed19021fSbcook
402ed19021fSbcook return (NULL);
403ed19021fSbcook }
404ed19021fSbcook
405ed19021fSbcook int
tls_accept_socket(struct tls * ctx,struct tls ** cctx,int s)406777595f3Sjsing tls_accept_socket(struct tls *ctx, struct tls **cctx, int s)
407ed19021fSbcook {
408777595f3Sjsing return (tls_accept_fds(ctx, cctx, s, s));
409ed19021fSbcook }
410ed19021fSbcook
411ed19021fSbcook int
tls_accept_fds(struct tls * ctx,struct tls ** cctx,int fd_read,int fd_write)412ed19021fSbcook tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
413ed19021fSbcook {
414ed19021fSbcook struct tls *conn_ctx;
415ed19021fSbcook
4162233a86cSjsing if ((conn_ctx = tls_accept_common(ctx)) == NULL)
417ed19021fSbcook goto err;
418ed19021fSbcook
419e1e4dea2Sjsing if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
420e1e4dea2Sjsing SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
4217a756d37Sjoshua tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4227a756d37Sjoshua "ssl file descriptor failure");
423b600beedSjsing goto err;
424b600beedSjsing }
425b600beedSjsing
426e2b71c11Sjsing *cctx = conn_ctx;
427b600beedSjsing
428b600beedSjsing return (0);
429b600beedSjsing err:
430e2b71c11Sjsing tls_free(conn_ctx);
431ed19021fSbcook *cctx = NULL;
432e2b71c11Sjsing
433ed19021fSbcook return (-1);
434ed19021fSbcook }
435ed19021fSbcook
436ed19021fSbcook int
tls_accept_cbs(struct tls * ctx,struct tls ** cctx,tls_read_cb read_cb,tls_write_cb write_cb,void * cb_arg)437ed19021fSbcook tls_accept_cbs(struct tls *ctx, struct tls **cctx,
438ed19021fSbcook tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg)
439ed19021fSbcook {
440ed19021fSbcook struct tls *conn_ctx;
441ed19021fSbcook
4422233a86cSjsing if ((conn_ctx = tls_accept_common(ctx)) == NULL)
443ed19021fSbcook goto err;
444ed19021fSbcook
44559bda8beSjsing if (tls_set_cbs(conn_ctx, read_cb, write_cb, cb_arg) != 0)
446ed19021fSbcook goto err;
447ed19021fSbcook
448ed19021fSbcook *cctx = conn_ctx;
449ed19021fSbcook
450ed19021fSbcook return (0);
451ed19021fSbcook err:
452ed19021fSbcook tls_free(conn_ctx);
453e2b71c11Sjsing *cctx = NULL;
454e2b71c11Sjsing
455b600beedSjsing return (-1);
456b600beedSjsing }
457e1e4dea2Sjsing
458e1e4dea2Sjsing int
tls_handshake_server(struct tls * ctx)459e2b71c11Sjsing tls_handshake_server(struct tls *ctx)
460e1e4dea2Sjsing {
461e2b71c11Sjsing int ssl_ret;
462e2b71c11Sjsing int rv = -1;
463e2b71c11Sjsing
464e2b71c11Sjsing if ((ctx->flags & TLS_SERVER_CONN) == 0) {
465*40ae7d6bSjoshua tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT,
4667a756d37Sjoshua "not a server connection context");
467e2b71c11Sjsing goto err;
468e2b71c11Sjsing }
469e2b71c11Sjsing
4705a752462Sjsing ctx->state |= TLS_SSL_NEEDS_SHUTDOWN;
4715a752462Sjsing
4729ba095aaSjsing ERR_clear_error();
473e2b71c11Sjsing if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) {
474e2b71c11Sjsing rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake");
475e2b71c11Sjsing goto err;
476e2b71c11Sjsing }
477e2b71c11Sjsing
478e2b71c11Sjsing ctx->state |= TLS_HANDSHAKE_COMPLETE;
479521d38f2Sbeck rv = 0;
480e2b71c11Sjsing
481e2b71c11Sjsing err:
482e2b71c11Sjsing return (rv);
483e1e4dea2Sjsing }
484