xref: /dragonfly/crypto/libressl/tls/tls_server.c (revision de0e0e4d)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: tls_server.c,v 1.48 2022/01/19 11:10:55 inoguchi Exp $ */
2f5b1c8a1SJohn Marino /*
3f5b1c8a1SJohn Marino  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * Permission to use, copy, modify, and distribute this software for any
6f5b1c8a1SJohn Marino  * purpose with or without fee is hereby granted, provided that the above
7f5b1c8a1SJohn Marino  * copyright notice and this permission notice appear in all copies.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10f5b1c8a1SJohn Marino  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11f5b1c8a1SJohn Marino  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12f5b1c8a1SJohn Marino  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13f5b1c8a1SJohn Marino  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14f5b1c8a1SJohn Marino  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15f5b1c8a1SJohn Marino  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f5b1c8a1SJohn Marino  */
17f5b1c8a1SJohn Marino 
1872c33676SMaxim Ag #include <sys/socket.h>
1972c33676SMaxim Ag 
2072c33676SMaxim Ag #include <arpa/inet.h>
2172c33676SMaxim Ag 
22f5b1c8a1SJohn Marino #include <openssl/ec.h>
23f5b1c8a1SJohn Marino #include <openssl/err.h>
24f5b1c8a1SJohn Marino #include <openssl/ssl.h>
25f5b1c8a1SJohn Marino 
26f5b1c8a1SJohn Marino #include <tls.h>
27f5b1c8a1SJohn Marino #include "tls_internal.h"
28f5b1c8a1SJohn Marino 
29f5b1c8a1SJohn Marino struct tls *
tls_server(void)30f5b1c8a1SJohn Marino tls_server(void)
31f5b1c8a1SJohn Marino {
32f5b1c8a1SJohn Marino 	struct tls *ctx;
33f5b1c8a1SJohn Marino 
3472c33676SMaxim Ag 	if (tls_init() == -1)
3572c33676SMaxim Ag 		return (NULL);
3672c33676SMaxim Ag 
37f5b1c8a1SJohn Marino 	if ((ctx = tls_new()) == NULL)
38f5b1c8a1SJohn Marino 		return (NULL);
39f5b1c8a1SJohn Marino 
40f5b1c8a1SJohn Marino 	ctx->flags |= TLS_SERVER;
41f5b1c8a1SJohn Marino 
42f5b1c8a1SJohn Marino 	return (ctx);
43f5b1c8a1SJohn Marino }
44f5b1c8a1SJohn Marino 
45f5b1c8a1SJohn Marino struct tls *
tls_server_conn(struct tls * ctx)46f5b1c8a1SJohn Marino tls_server_conn(struct tls *ctx)
47f5b1c8a1SJohn Marino {
48f5b1c8a1SJohn Marino 	struct tls *conn_ctx;
49f5b1c8a1SJohn Marino 
50f5b1c8a1SJohn Marino 	if ((conn_ctx = tls_new()) == NULL)
51f5b1c8a1SJohn Marino 		return (NULL);
52f5b1c8a1SJohn Marino 
53f5b1c8a1SJohn Marino 	conn_ctx->flags |= TLS_SERVER_CONN;
54f5b1c8a1SJohn Marino 
55cca6fc52SDaniel Fojt 	pthread_mutex_lock(&ctx->config->mutex);
5672c33676SMaxim Ag 	ctx->config->refcount++;
57cca6fc52SDaniel Fojt 	pthread_mutex_unlock(&ctx->config->mutex);
5872c33676SMaxim Ag 
5972c33676SMaxim Ag 	conn_ctx->config = ctx->config;
6072c33676SMaxim Ag 	conn_ctx->keypair = ctx->config->keypair;
6172c33676SMaxim Ag 
62f5b1c8a1SJohn Marino 	return (conn_ctx);
63f5b1c8a1SJohn Marino }
64f5b1c8a1SJohn Marino 
6572c33676SMaxim Ag static int
tls_server_alpn_cb(SSL * ssl,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)6672c33676SMaxim Ag tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
6772c33676SMaxim Ag     const unsigned char *in, unsigned int inlen, void *arg)
68f5b1c8a1SJohn Marino {
6972c33676SMaxim Ag 	struct tls *ctx = arg;
70f5b1c8a1SJohn Marino 
7172c33676SMaxim Ag 	if (SSL_select_next_proto((unsigned char**)out, outlen,
7272c33676SMaxim Ag 	    ctx->config->alpn, ctx->config->alpn_len, in, inlen) ==
7372c33676SMaxim Ag 	    OPENSSL_NPN_NEGOTIATED)
7472c33676SMaxim Ag 		return (SSL_TLSEXT_ERR_OK);
7572c33676SMaxim Ag 
7672c33676SMaxim Ag 	return (SSL_TLSEXT_ERR_NOACK);
7772c33676SMaxim Ag }
7872c33676SMaxim Ag 
7972c33676SMaxim Ag static int
tls_servername_cb(SSL * ssl,int * al,void * arg)8072c33676SMaxim Ag tls_servername_cb(SSL *ssl, int *al, void *arg)
8172c33676SMaxim Ag {
8272c33676SMaxim Ag 	struct tls *ctx = (struct tls *)arg;
8372c33676SMaxim Ag 	struct tls_sni_ctx *sni_ctx;
8472c33676SMaxim Ag 	union tls_addr addrbuf;
8572c33676SMaxim Ag 	struct tls *conn_ctx;
8672c33676SMaxim Ag 	const char *name;
8772c33676SMaxim Ag 	int match;
8872c33676SMaxim Ag 
8972c33676SMaxim Ag 	if ((conn_ctx = SSL_get_app_data(ssl)) == NULL)
9072c33676SMaxim Ag 		goto err;
9172c33676SMaxim Ag 
9272c33676SMaxim Ag 	if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) ==
9372c33676SMaxim Ag 	    NULL) {
9472c33676SMaxim Ag 		/*
9572c33676SMaxim Ag 		 * The servername callback gets called even when there is no
9672c33676SMaxim Ag 		 * TLS servername extension provided by the client. Sigh!
9772c33676SMaxim Ag 		 */
9872c33676SMaxim Ag 		return (SSL_TLSEXT_ERR_NOACK);
9972c33676SMaxim Ag 	}
10072c33676SMaxim Ag 
10172c33676SMaxim Ag 	/*
10272c33676SMaxim Ag 	 * Per RFC 6066 section 3: ensure that name is not an IP literal.
10372c33676SMaxim Ag 	 *
10472c33676SMaxim Ag 	 * While we should treat this as an error, a number of clients
10572c33676SMaxim Ag 	 * (Python, Ruby and Safari) are not RFC compliant. To avoid handshake
10672c33676SMaxim Ag 	 * failures, pretend that we did not receive the extension.
10772c33676SMaxim Ag 	 */
10872c33676SMaxim Ag 	if (inet_pton(AF_INET, name, &addrbuf) == 1 ||
10972c33676SMaxim Ag             inet_pton(AF_INET6, name, &addrbuf) == 1)
11072c33676SMaxim Ag 		return (SSL_TLSEXT_ERR_NOACK);
11172c33676SMaxim Ag 
112*de0e0e4dSAntonio Huete Jimenez 	free(conn_ctx->servername);
11372c33676SMaxim Ag 	if ((conn_ctx->servername = strdup(name)) == NULL)
11472c33676SMaxim Ag 		goto err;
11572c33676SMaxim Ag 
11672c33676SMaxim Ag 	/* Find appropriate SSL context for requested servername. */
11772c33676SMaxim Ag 	for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) {
11872c33676SMaxim Ag 		if (tls_check_name(ctx, sni_ctx->ssl_cert, name,
11972c33676SMaxim Ag 		    &match) == -1)
12072c33676SMaxim Ag 			goto err;
12172c33676SMaxim Ag 		if (match) {
12272c33676SMaxim Ag 			conn_ctx->keypair = sni_ctx->keypair;
12372c33676SMaxim Ag 			SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx);
12472c33676SMaxim Ag 			return (SSL_TLSEXT_ERR_OK);
12572c33676SMaxim Ag 		}
12672c33676SMaxim Ag 	}
12772c33676SMaxim Ag 
12872c33676SMaxim Ag 	/* No match, use the existing context/certificate. */
12972c33676SMaxim Ag 	return (SSL_TLSEXT_ERR_OK);
13072c33676SMaxim Ag 
13172c33676SMaxim Ag  err:
13272c33676SMaxim Ag 	/*
13372c33676SMaxim Ag 	 * There is no way to tell libssl that an internal failure occurred.
13472c33676SMaxim Ag 	 * The only option we have is to return a fatal alert.
13572c33676SMaxim Ag 	 */
136*de0e0e4dSAntonio Huete Jimenez 	*al = SSL_AD_INTERNAL_ERROR;
13772c33676SMaxim Ag 	return (SSL_TLSEXT_ERR_ALERT_FATAL);
13872c33676SMaxim Ag }
13972c33676SMaxim Ag 
14072c33676SMaxim Ag static struct tls_ticket_key *
tls_server_ticket_key(struct tls_config * config,unsigned char * keyname)14172c33676SMaxim Ag tls_server_ticket_key(struct tls_config *config, unsigned char *keyname)
14272c33676SMaxim Ag {
14372c33676SMaxim Ag 	struct tls_ticket_key *key = NULL;
14472c33676SMaxim Ag 	time_t now;
14572c33676SMaxim Ag 	int i;
14672c33676SMaxim Ag 
14772c33676SMaxim Ag 	now = time(NULL);
14872c33676SMaxim Ag 	if (config->ticket_autorekey == 1) {
14972c33676SMaxim Ag 		if (now - 3 * (config->session_lifetime / 4) >
15072c33676SMaxim Ag 		    config->ticket_keys[0].time) {
15172c33676SMaxim Ag 			if (tls_config_ticket_autorekey(config) == -1)
15272c33676SMaxim Ag 				return (NULL);
15372c33676SMaxim Ag 		}
15472c33676SMaxim Ag 	}
15572c33676SMaxim Ag 	for (i = 0; i < TLS_NUM_TICKETS; i++) {
15672c33676SMaxim Ag 		struct tls_ticket_key *tk = &config->ticket_keys[i];
15772c33676SMaxim Ag 		if (now - config->session_lifetime > tk->time)
15872c33676SMaxim Ag 			continue;
15972c33676SMaxim Ag 		if (keyname == NULL || timingsafe_memcmp(keyname,
16072c33676SMaxim Ag 		    tk->key_name, sizeof(tk->key_name)) == 0) {
16172c33676SMaxim Ag 			key = tk;
16272c33676SMaxim Ag 			break;
16372c33676SMaxim Ag 		}
16472c33676SMaxim Ag 	}
16572c33676SMaxim Ag 	return (key);
16672c33676SMaxim Ag }
16772c33676SMaxim Ag 
16872c33676SMaxim Ag static int
tls_server_ticket_cb(SSL * ssl,unsigned char * keyname,unsigned char * iv,EVP_CIPHER_CTX * ctx,HMAC_CTX * hctx,int mode)16972c33676SMaxim Ag tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv,
17072c33676SMaxim Ag     EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode)
17172c33676SMaxim Ag {
17272c33676SMaxim Ag 	struct tls_ticket_key *key;
17372c33676SMaxim Ag 	struct tls *tls_ctx;
17472c33676SMaxim Ag 
17572c33676SMaxim Ag 	if ((tls_ctx = SSL_get_app_data(ssl)) == NULL)
17672c33676SMaxim Ag 		return (-1);
17772c33676SMaxim Ag 
17872c33676SMaxim Ag 	if (mode == 1) {
17972c33676SMaxim Ag 		/* create new session */
18072c33676SMaxim Ag 		key = tls_server_ticket_key(tls_ctx->config, NULL);
18172c33676SMaxim Ag 		if (key == NULL) {
18272c33676SMaxim Ag 			tls_set_errorx(tls_ctx, "no valid ticket key found");
18372c33676SMaxim Ag 			return (-1);
18472c33676SMaxim Ag 		}
18572c33676SMaxim Ag 
18672c33676SMaxim Ag 		memcpy(keyname, key->key_name, sizeof(key->key_name));
18772c33676SMaxim Ag 		arc4random_buf(iv, EVP_MAX_IV_LENGTH);
188*de0e0e4dSAntonio Huete Jimenez 		if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
189*de0e0e4dSAntonio Huete Jimenez 		    key->aes_key, iv)) {
190*de0e0e4dSAntonio Huete Jimenez 			tls_set_errorx(tls_ctx, "failed to init encrypt");
191*de0e0e4dSAntonio Huete Jimenez 			return (-1);
192*de0e0e4dSAntonio Huete Jimenez 		}
193*de0e0e4dSAntonio Huete Jimenez 		if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
194*de0e0e4dSAntonio Huete Jimenez 		    EVP_sha256(), NULL)) {
195*de0e0e4dSAntonio Huete Jimenez 			tls_set_errorx(tls_ctx, "failed to init hmac");
196*de0e0e4dSAntonio Huete Jimenez 			return (-1);
197*de0e0e4dSAntonio Huete Jimenez 		}
19872c33676SMaxim Ag 		return (0);
19972c33676SMaxim Ag 	} else {
20072c33676SMaxim Ag 		/* get key by name */
20172c33676SMaxim Ag 		key = tls_server_ticket_key(tls_ctx->config, keyname);
20272c33676SMaxim Ag 		if (key == NULL)
20372c33676SMaxim Ag 			return (0);
20472c33676SMaxim Ag 
205*de0e0e4dSAntonio Huete Jimenez 		if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL,
206*de0e0e4dSAntonio Huete Jimenez 		    key->aes_key, iv)) {
207*de0e0e4dSAntonio Huete Jimenez 			tls_set_errorx(tls_ctx, "failed to init decrypt");
208*de0e0e4dSAntonio Huete Jimenez 			return (-1);
209*de0e0e4dSAntonio Huete Jimenez 		}
210*de0e0e4dSAntonio Huete Jimenez 		if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key),
211*de0e0e4dSAntonio Huete Jimenez 		    EVP_sha256(), NULL)) {
212*de0e0e4dSAntonio Huete Jimenez 			tls_set_errorx(tls_ctx, "failed to init hmac");
213*de0e0e4dSAntonio Huete Jimenez 			return (-1);
214*de0e0e4dSAntonio Huete Jimenez 		}
21572c33676SMaxim Ag 
21672c33676SMaxim Ag 		/* time to renew the ticket? is it the primary key? */
21772c33676SMaxim Ag 		if (key != &tls_ctx->config->ticket_keys[0])
21872c33676SMaxim Ag 			return (2);
21972c33676SMaxim Ag 		return (1);
22072c33676SMaxim Ag 	}
22172c33676SMaxim Ag }
22272c33676SMaxim Ag 
22372c33676SMaxim Ag static int
tls_configure_server_ssl(struct tls * ctx,SSL_CTX ** ssl_ctx,struct tls_keypair * keypair)22472c33676SMaxim Ag tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx,
22572c33676SMaxim Ag     struct tls_keypair *keypair)
22672c33676SMaxim Ag {
22772c33676SMaxim Ag 	SSL_CTX_free(*ssl_ctx);
22872c33676SMaxim Ag 
22972c33676SMaxim Ag 	if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
230f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "ssl context failure");
231f5b1c8a1SJohn Marino 		goto err;
232f5b1c8a1SJohn Marino 	}
233f5b1c8a1SJohn Marino 
23472c33676SMaxim Ag 	SSL_CTX_set_options(*ssl_ctx, SSL_OP_NO_CLIENT_RENEGOTIATION);
23572c33676SMaxim Ag 
23672c33676SMaxim Ag 	if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx,
23772c33676SMaxim Ag 	    tls_servername_cb) != 1) {
23872c33676SMaxim Ag 		tls_set_error(ctx, "failed to set servername callback");
239f5b1c8a1SJohn Marino 		goto err;
24072c33676SMaxim Ag 	}
24172c33676SMaxim Ag 	if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) {
24272c33676SMaxim Ag 		tls_set_error(ctx, "failed to set servername callback arg");
24372c33676SMaxim Ag 		goto err;
24472c33676SMaxim Ag 	}
24572c33676SMaxim Ag 
24672c33676SMaxim Ag 	if (tls_configure_ssl(ctx, *ssl_ctx) != 0)
24772c33676SMaxim Ag 		goto err;
24872c33676SMaxim Ag 	if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0)
249f5b1c8a1SJohn Marino 		goto err;
250f5b1c8a1SJohn Marino 	if (ctx->config->verify_client != 0) {
251f5b1c8a1SJohn Marino 		int verify = SSL_VERIFY_PEER;
252f5b1c8a1SJohn Marino 		if (ctx->config->verify_client == 1)
253f5b1c8a1SJohn Marino 			verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
25472c33676SMaxim Ag 		if (tls_configure_ssl_verify(ctx, *ssl_ctx, verify) == -1)
255f5b1c8a1SJohn Marino 			goto err;
256f5b1c8a1SJohn Marino 	}
257f5b1c8a1SJohn Marino 
25872c33676SMaxim Ag 	if (ctx->config->alpn != NULL)
25972c33676SMaxim Ag 		SSL_CTX_set_alpn_select_cb(*ssl_ctx, tls_server_alpn_cb,
26072c33676SMaxim Ag 		    ctx);
26172c33676SMaxim Ag 
262f5b1c8a1SJohn Marino 	if (ctx->config->dheparams == -1)
26372c33676SMaxim Ag 		SSL_CTX_set_dh_auto(*ssl_ctx, 1);
264f5b1c8a1SJohn Marino 	else if (ctx->config->dheparams == 1024)
26572c33676SMaxim Ag 		SSL_CTX_set_dh_auto(*ssl_ctx, 2);
266f5b1c8a1SJohn Marino 
26772c33676SMaxim Ag 	if (ctx->config->ecdhecurves != NULL) {
26872c33676SMaxim Ag 		SSL_CTX_set_ecdh_auto(*ssl_ctx, 1);
26972c33676SMaxim Ag 		if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves,
27072c33676SMaxim Ag 		    ctx->config->ecdhecurves_len) != 1) {
27172c33676SMaxim Ag 			tls_set_errorx(ctx, "failed to set ecdhe curves");
272f5b1c8a1SJohn Marino 			goto err;
273f5b1c8a1SJohn Marino 		}
274f5b1c8a1SJohn Marino 	}
275f5b1c8a1SJohn Marino 
276f5b1c8a1SJohn Marino 	if (ctx->config->ciphers_server == 1)
27772c33676SMaxim Ag 		SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
278f5b1c8a1SJohn Marino 
27972c33676SMaxim Ag 	if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) {
28072c33676SMaxim Ag 		tls_set_errorx(ctx, "failed to add OCSP stapling callback");
281f5b1c8a1SJohn Marino 		goto err;
282f5b1c8a1SJohn Marino 	}
283f5b1c8a1SJohn Marino 
28472c33676SMaxim Ag 	if (ctx->config->session_lifetime > 0) {
28572c33676SMaxim Ag 		/* set the session lifetime and enable tickets */
28672c33676SMaxim Ag 		SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime);
28772c33676SMaxim Ag 		SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET);
28872c33676SMaxim Ag 		if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx,
28972c33676SMaxim Ag 		    tls_server_ticket_cb)) {
29072c33676SMaxim Ag 			tls_set_error(ctx,
29172c33676SMaxim Ag 			    "failed to set the TLS ticket callback");
29272c33676SMaxim Ag 			goto err;
29372c33676SMaxim Ag 		}
29472c33676SMaxim Ag 	}
29572c33676SMaxim Ag 
29672c33676SMaxim Ag 	if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id,
29772c33676SMaxim Ag 	    sizeof(ctx->config->session_id)) != 1) {
29872c33676SMaxim Ag 		tls_set_error(ctx, "failed to set session id context");
29972c33676SMaxim Ag 		goto err;
30072c33676SMaxim Ag 	}
30172c33676SMaxim Ag 
30272c33676SMaxim Ag 	return (0);
30372c33676SMaxim Ag 
30472c33676SMaxim Ag   err:
30572c33676SMaxim Ag 	SSL_CTX_free(*ssl_ctx);
30672c33676SMaxim Ag 	*ssl_ctx = NULL;
30772c33676SMaxim Ag 
30872c33676SMaxim Ag 	return (-1);
30972c33676SMaxim Ag }
31072c33676SMaxim Ag 
31172c33676SMaxim Ag static int
tls_configure_server_sni(struct tls * ctx)31272c33676SMaxim Ag tls_configure_server_sni(struct tls *ctx)
31372c33676SMaxim Ag {
31472c33676SMaxim Ag 	struct tls_sni_ctx **sni_ctx;
31572c33676SMaxim Ag 	struct tls_keypair *kp;
31672c33676SMaxim Ag 
31772c33676SMaxim Ag 	if (ctx->config->keypair->next == NULL)
31872c33676SMaxim Ag 		return (0);
31972c33676SMaxim Ag 
32072c33676SMaxim Ag 	/* Set up additional SSL contexts for SNI. */
32172c33676SMaxim Ag 	sni_ctx = &ctx->sni_ctx;
32272c33676SMaxim Ag 	for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) {
32372c33676SMaxim Ag 		if ((*sni_ctx = tls_sni_ctx_new()) == NULL) {
32472c33676SMaxim Ag 			tls_set_errorx(ctx, "out of memory");
32572c33676SMaxim Ag 			goto err;
32672c33676SMaxim Ag 		}
32772c33676SMaxim Ag 		(*sni_ctx)->keypair = kp;
32872c33676SMaxim Ag 		if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1)
32972c33676SMaxim Ag 			goto err;
33072c33676SMaxim Ag 		if (tls_keypair_load_cert(kp, &ctx->error,
33172c33676SMaxim Ag 		    &(*sni_ctx)->ssl_cert) == -1)
33272c33676SMaxim Ag 			goto err;
33372c33676SMaxim Ag 		sni_ctx = &(*sni_ctx)->next;
33472c33676SMaxim Ag 	}
33572c33676SMaxim Ag 
336f5b1c8a1SJohn Marino 	return (0);
337f5b1c8a1SJohn Marino 
338f5b1c8a1SJohn Marino  err:
339f5b1c8a1SJohn Marino 	return (-1);
340f5b1c8a1SJohn Marino }
341f5b1c8a1SJohn Marino 
342f5b1c8a1SJohn Marino int
tls_configure_server(struct tls * ctx)34372c33676SMaxim Ag tls_configure_server(struct tls *ctx)
344f5b1c8a1SJohn Marino {
34572c33676SMaxim Ag 	if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx,
34672c33676SMaxim Ag 	    ctx->config->keypair) == -1)
34772c33676SMaxim Ag 		goto err;
34872c33676SMaxim Ag 	if (tls_configure_server_sni(ctx) == -1)
34972c33676SMaxim Ag 		goto err;
35072c33676SMaxim Ag 
35172c33676SMaxim Ag 	return (0);
35272c33676SMaxim Ag 
35372c33676SMaxim Ag  err:
35472c33676SMaxim Ag 	return (-1);
355f5b1c8a1SJohn Marino }
356f5b1c8a1SJohn Marino 
35772c33676SMaxim Ag static struct tls *
tls_accept_common(struct tls * ctx)35872c33676SMaxim Ag tls_accept_common(struct tls *ctx)
359f5b1c8a1SJohn Marino {
360f5b1c8a1SJohn Marino 	struct tls *conn_ctx = NULL;
361f5b1c8a1SJohn Marino 
362f5b1c8a1SJohn Marino 	if ((ctx->flags & TLS_SERVER) == 0) {
363f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "not a server context");
364f5b1c8a1SJohn Marino 		goto err;
365f5b1c8a1SJohn Marino 	}
366f5b1c8a1SJohn Marino 
367f5b1c8a1SJohn Marino 	if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
368f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "connection context failure");
369f5b1c8a1SJohn Marino 		goto err;
370f5b1c8a1SJohn Marino 	}
371f5b1c8a1SJohn Marino 
372f5b1c8a1SJohn Marino 	if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
373f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "ssl failure");
374f5b1c8a1SJohn Marino 		goto err;
375f5b1c8a1SJohn Marino 	}
37672c33676SMaxim Ag 
377f5b1c8a1SJohn Marino 	if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) {
378f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "ssl application data failure");
379f5b1c8a1SJohn Marino 		goto err;
380f5b1c8a1SJohn Marino 	}
38172c33676SMaxim Ag 
38272c33676SMaxim Ag 	return conn_ctx;
38372c33676SMaxim Ag 
38472c33676SMaxim Ag  err:
38572c33676SMaxim Ag 	tls_free(conn_ctx);
38672c33676SMaxim Ag 
38772c33676SMaxim Ag 	return (NULL);
38872c33676SMaxim Ag }
38972c33676SMaxim Ag 
39072c33676SMaxim Ag int
tls_accept_socket(struct tls * ctx,struct tls ** cctx,int s)39172c33676SMaxim Ag tls_accept_socket(struct tls *ctx, struct tls **cctx, int s)
39272c33676SMaxim Ag {
39372c33676SMaxim Ag 	return (tls_accept_fds(ctx, cctx, s, s));
39472c33676SMaxim Ag }
39572c33676SMaxim Ag 
39672c33676SMaxim Ag int
tls_accept_fds(struct tls * ctx,struct tls ** cctx,int fd_read,int fd_write)39772c33676SMaxim Ag tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
39872c33676SMaxim Ag {
39972c33676SMaxim Ag 	struct tls *conn_ctx;
40072c33676SMaxim Ag 
40172c33676SMaxim Ag 	if ((conn_ctx = tls_accept_common(ctx)) == NULL)
40272c33676SMaxim Ag 		goto err;
40372c33676SMaxim Ag 
404f5b1c8a1SJohn Marino 	if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
405f5b1c8a1SJohn Marino 	    SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
406f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "ssl file descriptor failure");
407f5b1c8a1SJohn Marino 		goto err;
408f5b1c8a1SJohn Marino 	}
409f5b1c8a1SJohn Marino 
410f5b1c8a1SJohn Marino 	*cctx = conn_ctx;
411f5b1c8a1SJohn Marino 
412f5b1c8a1SJohn Marino 	return (0);
413f5b1c8a1SJohn Marino  err:
414f5b1c8a1SJohn Marino 	tls_free(conn_ctx);
41572c33676SMaxim Ag 	*cctx = NULL;
416f5b1c8a1SJohn Marino 
41772c33676SMaxim Ag 	return (-1);
41872c33676SMaxim Ag }
41972c33676SMaxim Ag 
42072c33676SMaxim Ag int
tls_accept_cbs(struct tls * ctx,struct tls ** cctx,tls_read_cb read_cb,tls_write_cb write_cb,void * cb_arg)42172c33676SMaxim Ag tls_accept_cbs(struct tls *ctx, struct tls **cctx,
42272c33676SMaxim Ag     tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg)
42372c33676SMaxim Ag {
42472c33676SMaxim Ag 	struct tls *conn_ctx;
42572c33676SMaxim Ag 
42672c33676SMaxim Ag 	if ((conn_ctx = tls_accept_common(ctx)) == NULL)
42772c33676SMaxim Ag 		goto err;
42872c33676SMaxim Ag 
42972c33676SMaxim Ag 	if (tls_set_cbs(conn_ctx, read_cb, write_cb, cb_arg) != 0)
43072c33676SMaxim Ag 		goto err;
43172c33676SMaxim Ag 
43272c33676SMaxim Ag 	*cctx = conn_ctx;
43372c33676SMaxim Ag 
43472c33676SMaxim Ag 	return (0);
43572c33676SMaxim Ag  err:
43672c33676SMaxim Ag 	tls_free(conn_ctx);
437f5b1c8a1SJohn Marino 	*cctx = NULL;
438f5b1c8a1SJohn Marino 
439f5b1c8a1SJohn Marino 	return (-1);
440f5b1c8a1SJohn Marino }
441f5b1c8a1SJohn Marino 
442f5b1c8a1SJohn Marino int
tls_handshake_server(struct tls * ctx)443f5b1c8a1SJohn Marino tls_handshake_server(struct tls *ctx)
444f5b1c8a1SJohn Marino {
445f5b1c8a1SJohn Marino 	int ssl_ret;
446f5b1c8a1SJohn Marino 	int rv = -1;
447f5b1c8a1SJohn Marino 
448f5b1c8a1SJohn Marino 	if ((ctx->flags & TLS_SERVER_CONN) == 0) {
449f5b1c8a1SJohn Marino 		tls_set_errorx(ctx, "not a server connection context");
450f5b1c8a1SJohn Marino 		goto err;
451f5b1c8a1SJohn Marino 	}
452f5b1c8a1SJohn Marino 
45372c33676SMaxim Ag 	ctx->state |= TLS_SSL_NEEDS_SHUTDOWN;
45472c33676SMaxim Ag 
455f5b1c8a1SJohn Marino 	ERR_clear_error();
456f5b1c8a1SJohn Marino 	if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) {
457f5b1c8a1SJohn Marino 		rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake");
458f5b1c8a1SJohn Marino 		goto err;
459f5b1c8a1SJohn Marino 	}
460f5b1c8a1SJohn Marino 
461f5b1c8a1SJohn Marino 	ctx->state |= TLS_HANDSHAKE_COMPLETE;
462f5b1c8a1SJohn Marino 	rv = 0;
463f5b1c8a1SJohn Marino 
464f5b1c8a1SJohn Marino  err:
465f5b1c8a1SJohn Marino 	return (rv);
466f5b1c8a1SJohn Marino }
467