xref: /openbsd-src/lib/libtls/tls.c (revision 13bba76f4894ae7a858a165532710495146cef47)
1*13bba76fStb /* $OpenBSD: tls.c,v 1.104 2024/04/08 20:47:32 tb 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 
18b600beedSjsing #include <sys/socket.h>
19b600beedSjsing 
20b600beedSjsing #include <errno.h>
21c81cfcc3Sdoug #include <limits.h>
22c029eb32Sbeck #include <pthread.h>
23b600beedSjsing #include <stdlib.h>
24e6d77be9Sop #include <string.h>
25b600beedSjsing #include <unistd.h>
26b600beedSjsing 
27b600beedSjsing #include <openssl/bio.h>
28f832f19aSjsing #include <openssl/err.h>
29b600beedSjsing #include <openssl/evp.h>
30b600beedSjsing #include <openssl/pem.h>
3180bc881dSjsing #include <openssl/safestack.h>
3280bc881dSjsing #include <openssl/ssl.h>
33b600beedSjsing #include <openssl/x509.h>
34b600beedSjsing 
35b600beedSjsing #include <tls.h>
36b600beedSjsing #include "tls_internal.h"
37b600beedSjsing 
38b600beedSjsing static struct tls_config *tls_config_default;
39b600beedSjsing 
40c029eb32Sbeck static int tls_init_rv = -1;
41c029eb32Sbeck 
42c029eb32Sbeck static void
tls_do_init(void)43c029eb32Sbeck tls_do_init(void)
44b600beedSjsing {
45c650228dSjsing 	OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_CONFIG, NULL);
46b600beedSjsing 
471d3c3f1fSbcook 	if (BIO_sock_init() != 1)
48c029eb32Sbeck 		return;
491d3c3f1fSbcook 
50b9573a74Sjsing 	if ((tls_config_default = tls_config_new_internal()) == NULL)
51c029eb32Sbeck 		return;
52b600beedSjsing 
5388c10dabSjsing 	tls_config_default->refcount++;
5488c10dabSjsing 
55c029eb32Sbeck 	tls_init_rv = 0;
56c029eb32Sbeck }
57b600beedSjsing 
58c029eb32Sbeck int
tls_init(void)59c029eb32Sbeck tls_init(void)
60c029eb32Sbeck {
61c029eb32Sbeck 	static pthread_once_t once = PTHREAD_ONCE_INIT;
62c029eb32Sbeck 
63c029eb32Sbeck 	if (pthread_once(&once, tls_do_init) != 0)
64c029eb32Sbeck 		return -1;
65c029eb32Sbeck 
66c029eb32Sbeck 	return tls_init_rv;
67b600beedSjsing }
68b600beedSjsing 
69b600beedSjsing const char *
tls_error(struct tls * ctx)70b600beedSjsing tls_error(struct tls *ctx)
71b600beedSjsing {
72a88e9e95Sjsing 	return ctx->error.msg;
73b600beedSjsing }
74b600beedSjsing 
757a756d37Sjoshua int
tls_error_code(struct tls * ctx)767a756d37Sjoshua tls_error_code(struct tls *ctx)
777a756d37Sjoshua {
787a756d37Sjoshua 	return ctx->error.code;
797a756d37Sjoshua }
807a756d37Sjoshua 
819e219fcdSjsing void
tls_error_clear(struct tls_error * error)829e219fcdSjsing tls_error_clear(struct tls_error *error)
839e219fcdSjsing {
849e219fcdSjsing 	free(error->msg);
859e219fcdSjsing 	error->msg = NULL;
867a756d37Sjoshua 	error->code = TLS_ERROR_UNKNOWN;
87deae75adSjoshua 	error->errno_value = 0;
889e219fcdSjsing 	error->tls = 0;
899e219fcdSjsing }
909e219fcdSjsing 
91fdb1c79fSjsing static int
tls_error_vset(struct tls_error * error,int code,int errno_value,const char * fmt,va_list ap)927a756d37Sjoshua tls_error_vset(struct tls_error *error, int code, int errno_value,
937a756d37Sjoshua     const char *fmt, va_list ap)
94fdb1c79fSjsing {
95fdb1c79fSjsing 	char *errmsg = NULL;
96fdb1c79fSjsing 	int rv = -1;
97fdb1c79fSjsing 
989e219fcdSjsing 	tls_error_clear(error);
999e219fcdSjsing 
1007a756d37Sjoshua 	error->code = code;
101deae75adSjoshua 	error->errno_value = errno_value;
1029e219fcdSjsing 	error->tls = 1;
103fdb1c79fSjsing 
104fdb1c79fSjsing 	if (vasprintf(&errmsg, fmt, ap) == -1) {
105fdb1c79fSjsing 		errmsg = NULL;
106fdb1c79fSjsing 		goto err;
107fdb1c79fSjsing 	}
108fdb1c79fSjsing 
109deae75adSjoshua 	if (errno_value == -1) {
110a88e9e95Sjsing 		error->msg = errmsg;
111fdb1c79fSjsing 		return (0);
112fdb1c79fSjsing 	}
113fdb1c79fSjsing 
114deae75adSjoshua 	if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errno_value)) == -1) {
115a88e9e95Sjsing 		error->msg = NULL;
116fdb1c79fSjsing 		goto err;
117fdb1c79fSjsing 	}
118fdb1c79fSjsing 	rv = 0;
119fdb1c79fSjsing 
120fdb1c79fSjsing  err:
121fdb1c79fSjsing 	free(errmsg);
122fdb1c79fSjsing 
123fdb1c79fSjsing 	return (rv);
124fdb1c79fSjsing }
125fdb1c79fSjsing 
126b600beedSjsing int
tls_error_set(struct tls_error * error,int code,const char * fmt,...)1277a756d37Sjoshua tls_error_set(struct tls_error *error, int code, const char *fmt, ...)
128a88e9e95Sjsing {
129a88e9e95Sjsing 	va_list ap;
130deae75adSjoshua 	int errno_value, rv;
131a88e9e95Sjsing 
132deae75adSjoshua 	errno_value = errno;
133a88e9e95Sjsing 
134a88e9e95Sjsing 	va_start(ap, fmt);
1357a756d37Sjoshua 	rv = tls_error_vset(error, code, errno_value, fmt, ap);
136a88e9e95Sjsing 	va_end(ap);
137a88e9e95Sjsing 
138a88e9e95Sjsing 	return (rv);
139a88e9e95Sjsing }
140a88e9e95Sjsing 
141a88e9e95Sjsing int
tls_error_setx(struct tls_error * error,int code,const char * fmt,...)1427a756d37Sjoshua tls_error_setx(struct tls_error *error, int code, const char *fmt, ...)
143b600beedSjsing {
144b600beedSjsing 	va_list ap;
145b600beedSjsing 	int rv;
146b600beedSjsing 
147a88e9e95Sjsing 	va_start(ap, fmt);
1487a756d37Sjoshua 	rv = tls_error_vset(error, code, -1, fmt, ap);
149f8289792Sjsing 	va_end(ap);
150f8289792Sjsing 
151f8289792Sjsing 	return (rv);
152f8289792Sjsing }
153f8289792Sjsing 
154f8289792Sjsing int
tls_config_set_error(struct tls_config * config,int code,const char * fmt,...)1557a756d37Sjoshua tls_config_set_error(struct tls_config *config, int code, const char *fmt, ...)
156f8289792Sjsing {
157f8289792Sjsing 	va_list ap;
158aa2571bdSjoshua 	int errno_value, rv;
159f8289792Sjsing 
160aa2571bdSjoshua 	errno_value = errno;
161f8289792Sjsing 
162f8289792Sjsing 	va_start(ap, fmt);
1637a756d37Sjoshua 	rv = tls_error_vset(&config->error, code, errno_value, fmt, ap);
164f8289792Sjsing 	va_end(ap);
165f8289792Sjsing 
166f8289792Sjsing 	return (rv);
167f8289792Sjsing }
168f8289792Sjsing 
169f8289792Sjsing int
tls_config_set_errorx(struct tls_config * config,int code,const char * fmt,...)1707a756d37Sjoshua tls_config_set_errorx(struct tls_config *config, int code, const char *fmt, ...)
171f8289792Sjsing {
172f8289792Sjsing 	va_list ap;
173f8289792Sjsing 	int rv;
174f8289792Sjsing 
175f8289792Sjsing 	va_start(ap, fmt);
1767a756d37Sjoshua 	rv = tls_error_vset(&config->error, code, -1, fmt, ap);
177a88e9e95Sjsing 	va_end(ap);
178a88e9e95Sjsing 
179a88e9e95Sjsing 	return (rv);
180a88e9e95Sjsing }
181a88e9e95Sjsing 
182a88e9e95Sjsing int
tls_set_error(struct tls * ctx,int code,const char * fmt,...)1837a756d37Sjoshua tls_set_error(struct tls *ctx, int code, const char *fmt, ...)
184a88e9e95Sjsing {
185a88e9e95Sjsing 	va_list ap;
186aa2571bdSjoshua 	int errno_value, rv;
187a88e9e95Sjsing 
188aa2571bdSjoshua 	errno_value = errno;
189b600beedSjsing 
190b600beedSjsing 	va_start(ap, fmt);
1917a756d37Sjoshua 	rv = tls_error_vset(&ctx->error, code, errno_value, fmt, ap);
192fdb1c79fSjsing 	va_end(ap);
193fdb1c79fSjsing 
194fdb1c79fSjsing 	return (rv);
195fdb1c79fSjsing }
196fdb1c79fSjsing 
197fdb1c79fSjsing int
tls_set_errorx(struct tls * ctx,int code,const char * fmt,...)1987a756d37Sjoshua tls_set_errorx(struct tls *ctx, int code, const char *fmt, ...)
199fdb1c79fSjsing {
200fdb1c79fSjsing 	va_list ap;
201fdb1c79fSjsing 	int rv;
202fdb1c79fSjsing 
203fdb1c79fSjsing 	va_start(ap, fmt);
2047a756d37Sjoshua 	rv = tls_error_vset(&ctx->error, code, -1, fmt, ap);
205b600beedSjsing 	va_end(ap);
206b600beedSjsing 
207b600beedSjsing 	return (rv);
208b600beedSjsing }
209b600beedSjsing 
2109e219fcdSjsing int
tls_set_ssl_errorx(struct tls * ctx,int code,const char * fmt,...)2117a756d37Sjoshua tls_set_ssl_errorx(struct tls *ctx, int code, const char *fmt, ...)
2129e219fcdSjsing {
2139e219fcdSjsing 	va_list ap;
2149e219fcdSjsing 	int rv;
2159e219fcdSjsing 
2169e219fcdSjsing 	/* Only set an error if a more specific one does not already exist. */
2179e219fcdSjsing 	if (ctx->error.tls != 0)
2189e219fcdSjsing 		return (0);
2199e219fcdSjsing 
2209e219fcdSjsing 	va_start(ap, fmt);
2217a756d37Sjoshua 	rv = tls_error_vset(&ctx->error, code, -1, fmt, ap);
2229e219fcdSjsing 	va_end(ap);
2239e219fcdSjsing 
2249e219fcdSjsing 	return (rv);
2259e219fcdSjsing }
2269e219fcdSjsing 
227f89edc01Sjsing struct tls_sni_ctx *
tls_sni_ctx_new(void)228f89edc01Sjsing tls_sni_ctx_new(void)
229f89edc01Sjsing {
230f89edc01Sjsing 	return (calloc(1, sizeof(struct tls_sni_ctx)));
231f89edc01Sjsing }
232f89edc01Sjsing 
233f89edc01Sjsing void
tls_sni_ctx_free(struct tls_sni_ctx * sni_ctx)234f89edc01Sjsing tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx)
235f89edc01Sjsing {
236f89edc01Sjsing 	if (sni_ctx == NULL)
237f89edc01Sjsing 		return;
238f89edc01Sjsing 
239f89edc01Sjsing 	SSL_CTX_free(sni_ctx->ssl_ctx);
240f89edc01Sjsing 	X509_free(sni_ctx->ssl_cert);
241f89edc01Sjsing 
242f89edc01Sjsing 	free(sni_ctx);
243f89edc01Sjsing }
244f89edc01Sjsing 
245b600beedSjsing struct tls *
tls_new(void)246b600beedSjsing tls_new(void)
247b600beedSjsing {
248b600beedSjsing 	struct tls *ctx;
249b600beedSjsing 
250b600beedSjsing 	if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
251b600beedSjsing 		return (NULL);
252b600beedSjsing 
253b600beedSjsing 	tls_reset(ctx);
2549ee433b9Sjsing 
255e4972b9bSbeck 	if (tls_configure(ctx, tls_config_default) == -1) {
256e4972b9bSbeck 		free(ctx);
257e4972b9bSbeck 		return NULL;
258e4972b9bSbeck 	}
259b600beedSjsing 
260b600beedSjsing 	return (ctx);
261b600beedSjsing }
262b600beedSjsing 
263b600beedSjsing int
tls_configure(struct tls * ctx,struct tls_config * config)264b600beedSjsing tls_configure(struct tls *ctx, struct tls_config *config)
265b600beedSjsing {
266b600beedSjsing 	if (config == NULL)
267b600beedSjsing 		config = tls_config_default;
268b600beedSjsing 
269bebb943aSjsing 	pthread_mutex_lock(&config->mutex);
27088c10dabSjsing 	config->refcount++;
271bebb943aSjsing 	pthread_mutex_unlock(&config->mutex);
27288c10dabSjsing 
27388c10dabSjsing 	tls_config_free(ctx->config);
2749ee433b9Sjsing 
275b600beedSjsing 	ctx->config = config;
2769ee433b9Sjsing 	ctx->keypair = config->keypair;
277b600beedSjsing 
278b600beedSjsing 	if ((ctx->flags & TLS_SERVER) != 0)
279b600beedSjsing 		return (tls_configure_server(ctx));
280b600beedSjsing 
281b600beedSjsing 	return (0);
282b600beedSjsing }
283b600beedSjsing 
284b600beedSjsing int
tls_cert_hash(X509 * cert,char ** hash)285c793ca29Sbeck tls_cert_hash(X509 *cert, char **hash)
286c793ca29Sbeck {
287c793ca29Sbeck 	char d[EVP_MAX_MD_SIZE], *dhex = NULL;
288c793ca29Sbeck 	int dlen, rv = -1;
289c793ca29Sbeck 
2900a095d8fSjsing 	free(*hash);
291c793ca29Sbeck 	*hash = NULL;
2920a095d8fSjsing 
293c793ca29Sbeck 	if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1)
294c793ca29Sbeck 		goto err;
295c793ca29Sbeck 
296c793ca29Sbeck 	if (tls_hex_string(d, dlen, &dhex, NULL) != 0)
297c793ca29Sbeck 		goto err;
298c793ca29Sbeck 
299c793ca29Sbeck 	if (asprintf(hash, "SHA256:%s", dhex) == -1) {
300c793ca29Sbeck 		*hash = NULL;
301c793ca29Sbeck 		goto err;
302c793ca29Sbeck 	}
303c793ca29Sbeck 
304c793ca29Sbeck 	rv = 0;
305c793ca29Sbeck  err:
306c793ca29Sbeck 	free(dhex);
307c793ca29Sbeck 
308c793ca29Sbeck 	return (rv);
309c793ca29Sbeck }
310c793ca29Sbeck 
311c793ca29Sbeck int
tls_cert_pubkey_hash(X509 * cert,char ** hash)3122974e8f1Sjsing tls_cert_pubkey_hash(X509 *cert, char **hash)
3132974e8f1Sjsing {
3142974e8f1Sjsing 	char d[EVP_MAX_MD_SIZE], *dhex = NULL;
3152974e8f1Sjsing 	int dlen, rv = -1;
3162974e8f1Sjsing 
3172974e8f1Sjsing 	free(*hash);
3182974e8f1Sjsing 	*hash = NULL;
3192974e8f1Sjsing 
3202974e8f1Sjsing 	if (X509_pubkey_digest(cert, EVP_sha256(), d, &dlen) != 1)
3212974e8f1Sjsing 		goto err;
3222974e8f1Sjsing 
3232974e8f1Sjsing 	if (tls_hex_string(d, dlen, &dhex, NULL) != 0)
3242974e8f1Sjsing 		goto err;
3252974e8f1Sjsing 
3262974e8f1Sjsing 	if (asprintf(hash, "SHA256:%s", dhex) == -1) {
3272974e8f1Sjsing 		*hash = NULL;
3282974e8f1Sjsing 		goto err;
3292974e8f1Sjsing 	}
3302974e8f1Sjsing 
3312974e8f1Sjsing 	rv = 0;
3322974e8f1Sjsing 
3332974e8f1Sjsing  err:
3342974e8f1Sjsing 	free(dhex);
3352974e8f1Sjsing 
3362974e8f1Sjsing 	return (rv);
3372974e8f1Sjsing }
3382974e8f1Sjsing 
33915339a8cSeric static int
tls_keypair_to_pkey(struct tls * ctx,struct tls_keypair * keypair,EVP_PKEY ** pkey)34015339a8cSeric tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pkey)
34115339a8cSeric {
34215339a8cSeric 	BIO *bio = NULL;
34315339a8cSeric 	X509 *x509 = NULL;
34415339a8cSeric 	char *mem;
34515339a8cSeric 	size_t len;
34615339a8cSeric 	int ret = -1;
34715339a8cSeric 
34815339a8cSeric 	*pkey = NULL;
34915339a8cSeric 
35015339a8cSeric 	if (ctx->config->use_fake_private_key) {
35115339a8cSeric 		mem = keypair->cert_mem;
35215339a8cSeric 		len = keypair->cert_len;
35315339a8cSeric 	} else {
35415339a8cSeric 		mem = keypair->key_mem;
35515339a8cSeric 		len = keypair->key_len;
35615339a8cSeric 	}
35715339a8cSeric 
35815339a8cSeric 	if (mem == NULL)
35915339a8cSeric 		return (0);
36015339a8cSeric 
36115339a8cSeric 	if (len > INT_MAX) {
3622b31d1bdSjoshua 		tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
3637a756d37Sjoshua 		    ctx->config->use_fake_private_key ?
3642b31d1bdSjoshua 		    "certificate too long" : "key too long");
36515339a8cSeric 		goto err;
36615339a8cSeric 	}
36715339a8cSeric 
36815339a8cSeric 	if ((bio = BIO_new_mem_buf(mem, len)) == NULL) {
3697a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "failed to create buffer");
37015339a8cSeric 		goto err;
37115339a8cSeric 	}
37215339a8cSeric 
37315339a8cSeric 	if (ctx->config->use_fake_private_key) {
37415339a8cSeric 		if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb,
37515339a8cSeric 		    NULL)) == NULL) {
3767a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
3777a756d37Sjoshua 			    "failed to read X509 certificate");
37815339a8cSeric 			goto err;
37915339a8cSeric 		}
38015339a8cSeric 		if ((*pkey = X509_get_pubkey(x509)) == NULL) {
3817a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
3827a756d37Sjoshua 			    "failed to retrieve pubkey");
38315339a8cSeric 			goto err;
38415339a8cSeric 		}
38515339a8cSeric 	} else {
38615339a8cSeric 		if ((*pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
38715339a8cSeric 		    NULL)) ==  NULL) {
3887a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
3897a756d37Sjoshua 			    "failed to read private key");
39015339a8cSeric 			goto err;
39115339a8cSeric 		}
39215339a8cSeric 	}
39315339a8cSeric 
39415339a8cSeric 	ret = 0;
39515339a8cSeric  err:
39615339a8cSeric 	BIO_free(bio);
39715339a8cSeric 	X509_free(x509);
39815339a8cSeric 	return (ret);
39915339a8cSeric }
40015339a8cSeric 
401f8e1ec60Seric static int
tls_keypair_setup_pkey(struct tls * ctx,struct tls_keypair * keypair,EVP_PKEY * pkey)402f8e1ec60Seric tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey)
403f8e1ec60Seric {
4049ecbddc1Seric 	RSA_METHOD *rsa_method;
4059dba47cfSop 	EC_KEY_METHOD *ecdsa_method;
406f8e1ec60Seric 	RSA *rsa = NULL;
407f8e1ec60Seric 	EC_KEY *eckey = NULL;
408f8e1ec60Seric 	int ret = -1;
409f8e1ec60Seric 
410f8e1ec60Seric 	/* Only install the pubkey hash if fake private keys are used. */
411f8e1ec60Seric 	if (!ctx->config->skip_private_key_check)
412f8e1ec60Seric 		return (0);
413f8e1ec60Seric 
414f8e1ec60Seric 	if (keypair->pubkey_hash == NULL) {
4157a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "public key hash not set");
416f8e1ec60Seric 		goto err;
417f8e1ec60Seric 	}
418f8e1ec60Seric 
419f8e1ec60Seric 	switch (EVP_PKEY_id(pkey)) {
420f8e1ec60Seric 	case EVP_PKEY_RSA:
421f8e1ec60Seric 		if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL ||
422f8e1ec60Seric 		    RSA_set_ex_data(rsa, 0, keypair->pubkey_hash) == 0) {
4237a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4247a756d37Sjoshua 			    "RSA key setup failure");
425f8e1ec60Seric 			goto err;
426f8e1ec60Seric 		}
427508824d4Sop 		if (ctx->config->sign_cb != NULL) {
428508824d4Sop 			rsa_method = tls_signer_rsa_method();
429508824d4Sop 			if (rsa_method == NULL ||
4309ecbddc1Seric 			    RSA_set_ex_data(rsa, 1, ctx->config) == 0 ||
4319ecbddc1Seric 			    RSA_set_method(rsa, rsa_method) == 0) {
4327a756d37Sjoshua 				tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4337a756d37Sjoshua 				    "failed to setup RSA key");
4349ecbddc1Seric 				goto err;
4359ecbddc1Seric 			}
436508824d4Sop 		}
437508824d4Sop 		/* Reset the key to work around caching in OpenSSL 3. */
438508824d4Sop 		if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) {
4397a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4407a756d37Sjoshua 			    "failed to set RSA key");
441508824d4Sop 			goto err;
442508824d4Sop 		}
443f8e1ec60Seric 		break;
444f8e1ec60Seric 	case EVP_PKEY_EC:
445f8e1ec60Seric 		if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL ||
4469dba47cfSop 		    EC_KEY_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) {
4477a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4487a756d37Sjoshua 			    "EC key setup failure");
449f8e1ec60Seric 			goto err;
450f8e1ec60Seric 		}
451508824d4Sop 		if (ctx->config->sign_cb != NULL) {
452508824d4Sop 			ecdsa_method = tls_signer_ecdsa_method();
453508824d4Sop 			if (ecdsa_method == NULL ||
4549dba47cfSop 			    EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 ||
4559dba47cfSop 			    EC_KEY_set_method(eckey, ecdsa_method) == 0) {
4567a756d37Sjoshua 				tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4577a756d37Sjoshua 				    "failed to setup EC key");
4589ecbddc1Seric 				goto err;
4599ecbddc1Seric 			}
460508824d4Sop 		}
461508824d4Sop 		/* Reset the key to work around caching in OpenSSL 3. */
462508824d4Sop 		if (EVP_PKEY_set1_EC_KEY(pkey, eckey) == 0) {
4637a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
4647a756d37Sjoshua 			    "failed to set EC key");
465508824d4Sop 			goto err;
466508824d4Sop 		}
467f8e1ec60Seric 		break;
468f8e1ec60Seric 	default:
4697a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "incorrect key type");
470f8e1ec60Seric 		goto err;
471f8e1ec60Seric 	}
472f8e1ec60Seric 
473f8e1ec60Seric 	ret = 0;
474f8e1ec60Seric 
475f8e1ec60Seric  err:
476f8e1ec60Seric 	RSA_free(rsa);
477f8e1ec60Seric 	EC_KEY_free(eckey);
478f8e1ec60Seric 	return (ret);
479f8e1ec60Seric }
480f8e1ec60Seric 
4812974e8f1Sjsing int
tls_configure_ssl_keypair(struct tls * ctx,SSL_CTX * ssl_ctx,struct tls_keypair * keypair,int required)482b7f318e7Sjsing tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx,
4831fe9fea1Sjsing     struct tls_keypair *keypair, int required)
484b600beedSjsing {
485b600beedSjsing 	EVP_PKEY *pkey = NULL;
486b600beedSjsing 
48751f3bd3dSbeck 	if (!required &&
4881fe9fea1Sjsing 	    keypair->cert_mem == NULL &&
48903ce4948Sjsing 	    keypair->key_mem == NULL)
49051f3bd3dSbeck 		return(0);
49151f3bd3dSbeck 
4921fe9fea1Sjsing 	if (keypair->cert_mem != NULL) {
4931fe9fea1Sjsing 		if (keypair->cert_len > INT_MAX) {
4942b31d1bdSjoshua 			tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
4957a756d37Sjoshua 			    "certificate too long");
496c81cfcc3Sdoug 			goto err;
497c81cfcc3Sdoug 		}
498c81cfcc3Sdoug 
4991fe9fea1Sjsing 		if (SSL_CTX_use_certificate_chain_mem(ssl_ctx,
5001fe9fea1Sjsing 		    keypair->cert_mem, keypair->cert_len) != 1) {
5017a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
5027a756d37Sjoshua 			    "failed to load certificate");
503b600beedSjsing 			goto err;
504b600beedSjsing 		}
505b600beedSjsing 	}
506c793ca29Sbeck 
50715339a8cSeric 	if (tls_keypair_to_pkey(ctx, keypair, &pkey) == -1)
508c81cfcc3Sdoug 		goto err;
50915339a8cSeric 	if (pkey != NULL) {
510f8e1ec60Seric 		if (tls_keypair_setup_pkey(ctx, keypair, pkey) == -1)
511f8e1ec60Seric 			goto err;
5121fe9fea1Sjsing 		if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) {
5137a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
5147a756d37Sjoshua 			    "failed to load private key");
515b600beedSjsing 			goto err;
516b600beedSjsing 		}
517b600beedSjsing 		EVP_PKEY_free(pkey);
518b600beedSjsing 		pkey = NULL;
519b600beedSjsing 	}
520b600beedSjsing 
521c793ca29Sbeck 	if (!ctx->config->skip_private_key_check &&
522c793ca29Sbeck 	    SSL_CTX_check_private_key(ssl_ctx) != 1) {
5237a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
5247a756d37Sjoshua 		    "private/public key mismatch");
525b600beedSjsing 		goto err;
526b600beedSjsing 	}
527b600beedSjsing 
528b600beedSjsing 	return (0);
529b600beedSjsing 
530b600beedSjsing  err:
531b600beedSjsing 	EVP_PKEY_free(pkey);
532b600beedSjsing 
533b609dc20Seric 	return (-1);
534b600beedSjsing }
535b600beedSjsing 
536b600beedSjsing int
tls_configure_ssl(struct tls * ctx,SSL_CTX * ssl_ctx)537b7f318e7Sjsing tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx)
538b600beedSjsing {
5393c640480Sjsing 	SSL_CTX_clear_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
5403c640480Sjsing 
541b7f318e7Sjsing 	SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
542b7f318e7Sjsing 	SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
54377b60f9aSbluhm 
544b7f318e7Sjsing 	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2);
545b7f318e7Sjsing 	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3);
5465c389b79Sbeck 	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1);
5475c389b79Sbeck 	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1);
548b600beedSjsing 
549b7f318e7Sjsing 	SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
5504c479435Sjsing 	SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_3);
551b600beedSjsing 
552b600beedSjsing 	if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0)
553b7f318e7Sjsing 		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2);
5544c479435Sjsing 	if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_3) == 0)
5554c479435Sjsing 		SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3);
556b600beedSjsing 
557183da8c6Sjsing 	if (ctx->config->alpn != NULL) {
558b7f318e7Sjsing 		if (SSL_CTX_set_alpn_protos(ssl_ctx, ctx->config->alpn,
559183da8c6Sjsing 		    ctx->config->alpn_len) != 0) {
5607a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
5617a756d37Sjoshua 			    "failed to set alpn");
562183da8c6Sjsing 			goto err;
563183da8c6Sjsing 		}
564183da8c6Sjsing 	}
565183da8c6Sjsing 
566b600beedSjsing 	if (ctx->config->ciphers != NULL) {
567b7f318e7Sjsing 		if (SSL_CTX_set_cipher_list(ssl_ctx,
568b600beedSjsing 		    ctx->config->ciphers) != 1) {
5697a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
5707a756d37Sjoshua 			    "failed to set ciphers");
571b600beedSjsing 			goto err;
572b600beedSjsing 		}
573b600beedSjsing 	}
574b600beedSjsing 
575615956a0Sjsing 	if (ctx->config->verify_time == 0) {
57661298c2bSjsing 		X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(ssl_ctx),
577615956a0Sjsing 		    X509_V_FLAG_NO_CHECK_TIME);
578615956a0Sjsing 	}
579615956a0Sjsing 
5808aee94d7Sclaudio 	/* Disable any form of session caching by default */
5818aee94d7Sclaudio 	SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF);
5828aee94d7Sclaudio 	SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
5838aee94d7Sclaudio 
584b600beedSjsing 	return (0);
585b600beedSjsing 
586b600beedSjsing  err:
587b600beedSjsing 	return (-1);
588b600beedSjsing }
589b600beedSjsing 
590888c565eSjsing static int
tls_ssl_cert_verify_cb(X509_STORE_CTX * x509_ctx,void * arg)591888c565eSjsing tls_ssl_cert_verify_cb(X509_STORE_CTX *x509_ctx, void *arg)
592888c565eSjsing {
593888c565eSjsing 	struct tls *ctx = arg;
5948147afa4Sjsing 	int x509_err;
595888c565eSjsing 
596888c565eSjsing 	if (ctx->config->verify_cert == 0)
597888c565eSjsing 		return (1);
598888c565eSjsing 
5998147afa4Sjsing 	if ((X509_verify_cert(x509_ctx)) < 0) {
6007a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6017a756d37Sjoshua 		    "X509 verify cert failed");
602888c565eSjsing 		return (0);
603888c565eSjsing 	}
604888c565eSjsing 
605888c565eSjsing 	x509_err = X509_STORE_CTX_get_error(x509_ctx);
6068147afa4Sjsing 	if (x509_err == X509_V_OK)
6078147afa4Sjsing 		return (1);
608888c565eSjsing 
6097a756d37Sjoshua 	tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6107a756d37Sjoshua 	    "certificate verification failed: %s",
611888c565eSjsing 	    X509_verify_cert_error_string(x509_err));
612888c565eSjsing 
613888c565eSjsing 	return (0);
614888c565eSjsing }
615888c565eSjsing 
61651f3bd3dSbeck int
tls_configure_ssl_verify(struct tls * ctx,SSL_CTX * ssl_ctx,int verify)617b7f318e7Sjsing tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify)
61851f3bd3dSbeck {
61903ce4948Sjsing 	size_t ca_len = ctx->config->ca_len;
62003ce4948Sjsing 	char *ca_mem = ctx->config->ca_mem;
62180bc881dSjsing 	char *crl_mem = ctx->config->crl_mem;
62280bc881dSjsing 	size_t crl_len = ctx->config->crl_len;
62303ce4948Sjsing 	char *ca_free = NULL;
62480bc881dSjsing 	STACK_OF(X509_INFO) *xis = NULL;
62580bc881dSjsing 	X509_STORE *store;
62680bc881dSjsing 	X509_INFO *xi;
62780bc881dSjsing 	BIO *bio = NULL;
628888c565eSjsing 	int rv = -1;
62980bc881dSjsing 	int i;
63003ce4948Sjsing 
631b7f318e7Sjsing 	SSL_CTX_set_verify(ssl_ctx, verify, NULL);
63217d46c2aSjsing 	SSL_CTX_set_cert_verify_callback(ssl_ctx, tls_ssl_cert_verify_cb, ctx);
63317d46c2aSjsing 
63417d46c2aSjsing 	if (ctx->config->verify_depth >= 0)
63517d46c2aSjsing 		SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth);
63617d46c2aSjsing 
63717d46c2aSjsing 	if (ctx->config->verify_cert == 0)
63817d46c2aSjsing 		goto done;
63951f3bd3dSbeck 
64003ce4948Sjsing 	/* If no CA has been specified, attempt to load the default. */
64103ce4948Sjsing 	if (ctx->config->ca_mem == NULL && ctx->config->ca_path == NULL) {
642f6b75673Stedu 		if (tls_config_load_file(&ctx->error, "CA", tls_default_ca_cert_file(),
64303ce4948Sjsing 		    &ca_mem, &ca_len) != 0)
64403ce4948Sjsing 			goto err;
64503ce4948Sjsing 		ca_free = ca_mem;
64603ce4948Sjsing 	}
64703ce4948Sjsing 
64803ce4948Sjsing 	if (ca_mem != NULL) {
64903ce4948Sjsing 		if (ca_len > INT_MAX) {
6502b31d1bdSjoshua 			tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
6512b31d1bdSjoshua 			    "ca too long");
65251f3bd3dSbeck 			goto err;
65351f3bd3dSbeck 		}
654b7f318e7Sjsing 		if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) {
6557a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6567a756d37Sjoshua 			    "ssl verify memory setup failure");
65751f3bd3dSbeck 			goto err;
65851f3bd3dSbeck 		}
659b7f318e7Sjsing 	} else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL,
66003ce4948Sjsing 	    ctx->config->ca_path) != 1) {
6617a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6627a756d37Sjoshua 		    "ssl verify locations failure");
66351f3bd3dSbeck 		goto err;
66451f3bd3dSbeck 	}
66521514b59Sjsing 
66680bc881dSjsing 	if (crl_mem != NULL) {
66780bc881dSjsing 		if (crl_len > INT_MAX) {
6682b31d1bdSjoshua 			tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
6692b31d1bdSjoshua 			    "crl too long");
67080bc881dSjsing 			goto err;
67180bc881dSjsing 		}
67280bc881dSjsing 		if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) {
6737a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6747a756d37Sjoshua 			    "failed to create buffer");
67580bc881dSjsing 			goto err;
67680bc881dSjsing 		}
67780bc881dSjsing 		if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb,
67880bc881dSjsing 		    NULL)) == NULL) {
6797a756d37Sjoshua 			tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
6807a756d37Sjoshua 			    "failed to parse crl");
68180bc881dSjsing 			goto err;
68280bc881dSjsing 		}
68380bc881dSjsing 		store = SSL_CTX_get_cert_store(ssl_ctx);
68480bc881dSjsing 		for (i = 0; i < sk_X509_INFO_num(xis); i++) {
68580bc881dSjsing 			xi = sk_X509_INFO_value(xis, i);
68680bc881dSjsing 			if (xi->crl == NULL)
68780bc881dSjsing 				continue;
68880bc881dSjsing 			if (!X509_STORE_add_crl(store, xi->crl)) {
6897a756d37Sjoshua 				tls_set_error(ctx, TLS_ERROR_UNKNOWN,
6907a756d37Sjoshua 				    "failed to add crl");
69180bc881dSjsing 				goto err;
69280bc881dSjsing 			}
69380bc881dSjsing 		}
694cbc8ac2bStb 		X509_STORE_set_flags(store,
69580bc881dSjsing 		    X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
69680bc881dSjsing 	}
69780bc881dSjsing 
69817d46c2aSjsing  done:
699888c565eSjsing 	rv = 0;
70051f3bd3dSbeck 
70151f3bd3dSbeck  err:
70280bc881dSjsing 	sk_X509_INFO_pop_free(xis, X509_INFO_free);
70380bc881dSjsing 	BIO_free(bio);
70403ce4948Sjsing 	free(ca_free);
70503ce4948Sjsing 
706888c565eSjsing 	return (rv);
70751f3bd3dSbeck }
70851f3bd3dSbeck 
709b600beedSjsing void
tls_free(struct tls * ctx)710b600beedSjsing tls_free(struct tls *ctx)
711b600beedSjsing {
712b600beedSjsing 	if (ctx == NULL)
713b600beedSjsing 		return;
714dc559dc0Sjsing 
715b600beedSjsing 	tls_reset(ctx);
716dc559dc0Sjsing 
717b600beedSjsing 	free(ctx);
718b600beedSjsing }
719b600beedSjsing 
720b600beedSjsing void
tls_reset(struct tls * ctx)721b600beedSjsing tls_reset(struct tls *ctx)
722b600beedSjsing {
723f89edc01Sjsing 	struct tls_sni_ctx *sni, *nsni;
724f89edc01Sjsing 
72588c10dabSjsing 	tls_config_free(ctx->config);
72688c10dabSjsing 	ctx->config = NULL;
72788c10dabSjsing 
728b600beedSjsing 	SSL_CTX_free(ctx->ssl_ctx);
729b600beedSjsing 	SSL_free(ctx->ssl_conn);
730e98425b4Sjsing 	X509_free(ctx->ssl_peer_cert);
731b600beedSjsing 
732b600beedSjsing 	ctx->ssl_conn = NULL;
733b600beedSjsing 	ctx->ssl_ctx = NULL;
734e98425b4Sjsing 	ctx->ssl_peer_cert = NULL;
735c67861f7Sbeck 	/* X509 objects in chain are freed with the SSL */
736c67861f7Sbeck 	ctx->ssl_peer_chain = NULL;
737b600beedSjsing 
738b600beedSjsing 	ctx->socket = -1;
73993310cfaSjsing 	ctx->state = 0;
740b600beedSjsing 
741e2b71c11Sjsing 	free(ctx->servername);
742e2b71c11Sjsing 	ctx->servername = NULL;
743e2b71c11Sjsing 
744a88e9e95Sjsing 	free(ctx->error.msg);
745a88e9e95Sjsing 	ctx->error.msg = NULL;
746deae75adSjoshua 	ctx->error.errno_value = -1;
747ab8f2ec6Sbeck 
748dc559dc0Sjsing 	tls_conninfo_free(ctx->conninfo);
749ab8f2ec6Sbeck 	ctx->conninfo = NULL;
750f89edc01Sjsing 
7516ffc3042Sbeck 	tls_ocsp_free(ctx->ocsp);
7526ffc3042Sbeck 	ctx->ocsp = NULL;
7532dc6b4e4Sbeck 
754f89edc01Sjsing 	for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) {
755f89edc01Sjsing 		nsni = sni->next;
756f89edc01Sjsing 		tls_sni_ctx_free(sni);
757f89edc01Sjsing 	}
758f89edc01Sjsing 	ctx->sni_ctx = NULL;
759ed19021fSbcook 
760ed19021fSbcook 	ctx->read_cb = NULL;
761ed19021fSbcook 	ctx->write_cb = NULL;
762ed19021fSbcook 	ctx->cb_arg = NULL;
763b600beedSjsing }
764b600beedSjsing 
765d474f84fSjsing int
tls_ssl_error(struct tls * ctx,SSL * ssl_conn,int ssl_ret,const char * prefix)7665251ab8eSjsing tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix)
767f832f19aSjsing {
768f832f19aSjsing 	const char *errstr = "unknown error";
769f832f19aSjsing 	unsigned long err;
770f832f19aSjsing 	int ssl_err;
771f832f19aSjsing 
7725251ab8eSjsing 	ssl_err = SSL_get_error(ssl_conn, ssl_ret);
773f832f19aSjsing 	switch (ssl_err) {
774f832f19aSjsing 	case SSL_ERROR_NONE:
775f832f19aSjsing 	case SSL_ERROR_ZERO_RETURN:
7762c02f8b2Sjsing 		return (0);
777f832f19aSjsing 
778f832f19aSjsing 	case SSL_ERROR_WANT_READ:
779ab00dbefSbeck 		return (TLS_WANT_POLLIN);
780f832f19aSjsing 
781f832f19aSjsing 	case SSL_ERROR_WANT_WRITE:
782ab00dbefSbeck 		return (TLS_WANT_POLLOUT);
783f832f19aSjsing 
784f832f19aSjsing 	case SSL_ERROR_SYSCALL:
785f832f19aSjsing 		if ((err = ERR_peek_error()) != 0) {
786f832f19aSjsing 			errstr = ERR_error_string(err, NULL);
787f832f19aSjsing 		} else if (ssl_ret == 0) {
78838c90daaSjsing 			if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) {
78939389942Sjsing 				ctx->state |= TLS_EOF_NO_CLOSE_NOTIFY;
79039389942Sjsing 				return (0);
79138c90daaSjsing 			}
79238c90daaSjsing 			errstr = "unexpected EOF";
793f832f19aSjsing 		} else if (ssl_ret == -1) {
794f832f19aSjsing 			errstr = strerror(errno);
795f832f19aSjsing 		}
7967a756d37Sjoshua 		tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN,
7977a756d37Sjoshua 		    "%s failed: %s", prefix, errstr);
798f832f19aSjsing 		return (-1);
799f832f19aSjsing 
800f832f19aSjsing 	case SSL_ERROR_SSL:
801f832f19aSjsing 		if ((err = ERR_peek_error()) != 0) {
802f832f19aSjsing 			errstr = ERR_error_string(err, NULL);
803f832f19aSjsing 		}
8047a756d37Sjoshua 		tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN,
8057a756d37Sjoshua 		    "%s failed: %s", prefix, errstr);
806f832f19aSjsing 		return (-1);
807f832f19aSjsing 
808f832f19aSjsing 	case SSL_ERROR_WANT_CONNECT:
809f832f19aSjsing 	case SSL_ERROR_WANT_ACCEPT:
810f832f19aSjsing 	case SSL_ERROR_WANT_X509_LOOKUP:
811f832f19aSjsing 	default:
8127a756d37Sjoshua 		tls_set_ssl_errorx(ctx, TLS_ERROR_UNKNOWN,
8137a756d37Sjoshua 		    "%s failed (%d)", prefix, ssl_err);
814f832f19aSjsing 		return (-1);
815f832f19aSjsing 	}
816f832f19aSjsing }
817f832f19aSjsing 
818b600beedSjsing int
tls_handshake(struct tls * ctx)819e2b71c11Sjsing tls_handshake(struct tls *ctx)
820e2b71c11Sjsing {
821e2b71c11Sjsing 	int rv = -1;
822e2b71c11Sjsing 
8239e219fcdSjsing 	tls_error_clear(&ctx->error);
8249e219fcdSjsing 
825cb3c676dSjsing 	if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
82640ae7d6bSjoshua 		tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT,
8277a756d37Sjoshua 		    "invalid operation for context");
828cb3c676dSjsing 		goto out;
829cb3c676dSjsing 	}
830cb3c676dSjsing 
831ef1e76eaSjsing 	if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) {
8327a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN,
8337a756d37Sjoshua 		    "handshake already completed");
834ef1e76eaSjsing 		goto out;
835ef1e76eaSjsing 	}
836ef1e76eaSjsing 
837e2b71c11Sjsing 	if ((ctx->flags & TLS_CLIENT) != 0)
838e2b71c11Sjsing 		rv = tls_handshake_client(ctx);
839e2b71c11Sjsing 	else if ((ctx->flags & TLS_SERVER_CONN) != 0)
840e2b71c11Sjsing 		rv = tls_handshake_server(ctx);
841e2b71c11Sjsing 
842cbeeb52cSbeck 	if (rv == 0) {
843cbeeb52cSbeck 		ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn);
844c67861f7Sbeck 		ctx->ssl_peer_chain = SSL_get_peer_cert_chain(ctx->ssl_conn);
845dc559dc0Sjsing 		if (tls_conninfo_populate(ctx) == -1)
846ab8f2ec6Sbeck 			rv = -1;
8476ffc3042Sbeck 		if (ctx->ocsp == NULL)
8486ffc3042Sbeck 			ctx->ocsp = tls_ocsp_setup_from_peer(ctx);
849cbeeb52cSbeck 	}
850ab8f2ec6Sbeck  out:
85141dd5705Sbeck 	/* Prevent callers from performing incorrect error handling */
852e2b71c11Sjsing 	errno = 0;
853e2b71c11Sjsing 	return (rv);
854e2b71c11Sjsing }
855e2b71c11Sjsing 
8561eeda1ffSbeck ssize_t
tls_read(struct tls * ctx,void * buf,size_t buflen)8571eeda1ffSbeck tls_read(struct tls *ctx, void *buf, size_t buflen)
858b600beedSjsing {
8591eeda1ffSbeck 	ssize_t rv = -1;
860f832f19aSjsing 	int ssl_ret;
86198f83bbfSjsing 
8629e219fcdSjsing 	tls_error_clear(&ctx->error);
8639e219fcdSjsing 
864e2b71c11Sjsing 	if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
865e2b71c11Sjsing 		if ((rv = tls_handshake(ctx)) != 0)
866e2b71c11Sjsing 			goto out;
867e2b71c11Sjsing 	}
868e2b71c11Sjsing 
869c81cfcc3Sdoug 	if (buflen > INT_MAX) {
8702b31d1bdSjoshua 		tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
8717a756d37Sjoshua 		    "buflen too long");
872b71eb829Sbeck 		goto out;
873c81cfcc3Sdoug 	}
874c81cfcc3Sdoug 
8759ba095aaSjsing 	ERR_clear_error();
87639389942Sjsing 	if ((ssl_ret = SSL_read(ctx->ssl_conn, buf, buflen)) > 0) {
8771eeda1ffSbeck 		rv = (ssize_t)ssl_ret;
878b71eb829Sbeck 		goto out;
879b600beedSjsing 	}
8801eeda1ffSbeck 	rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "read");
8819ba095aaSjsing 
882b71eb829Sbeck  out:
88341dd5705Sbeck 	/* Prevent callers from performing incorrect error handling */
884b71eb829Sbeck 	errno = 0;
885b71eb829Sbeck 	return (rv);
886b600beedSjsing }
887b600beedSjsing 
8881eeda1ffSbeck ssize_t
tls_write(struct tls * ctx,const void * buf,size_t buflen)8891eeda1ffSbeck tls_write(struct tls *ctx, const void *buf, size_t buflen)
890b600beedSjsing {
8911eeda1ffSbeck 	ssize_t rv = -1;
892f832f19aSjsing 	int ssl_ret;
89398f83bbfSjsing 
8949e219fcdSjsing 	tls_error_clear(&ctx->error);
8959e219fcdSjsing 
896e2b71c11Sjsing 	if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
897e2b71c11Sjsing 		if ((rv = tls_handshake(ctx)) != 0)
898e2b71c11Sjsing 			goto out;
899e2b71c11Sjsing 	}
900e2b71c11Sjsing 
901c81cfcc3Sdoug 	if (buflen > INT_MAX) {
9022b31d1bdSjoshua 		tls_set_errorx(ctx, TLS_ERROR_INVALID_ARGUMENT,
9037a756d37Sjoshua 		    "buflen too long");
904b71eb829Sbeck 		goto out;
905c81cfcc3Sdoug 	}
906c81cfcc3Sdoug 
9079ba095aaSjsing 	ERR_clear_error();
90839389942Sjsing 	if ((ssl_ret = SSL_write(ctx->ssl_conn, buf, buflen)) > 0) {
9091eeda1ffSbeck 		rv = (ssize_t)ssl_ret;
910b71eb829Sbeck 		goto out;
911b600beedSjsing 	}
9121eeda1ffSbeck 	rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "write");
9139ba095aaSjsing 
914b71eb829Sbeck  out:
91541dd5705Sbeck 	/* Prevent callers from performing incorrect error handling */
916b71eb829Sbeck 	errno = 0;
917b71eb829Sbeck 	return (rv);
918b600beedSjsing }
919b600beedSjsing 
920b600beedSjsing int
tls_close(struct tls * ctx)921b600beedSjsing tls_close(struct tls *ctx)
922b600beedSjsing {
923d29228b9Sjsing 	int ssl_ret;
9246dce3cf3Sjsing 	int rv = 0;
925d29228b9Sjsing 
9269e219fcdSjsing 	tls_error_clear(&ctx->error);
9279e219fcdSjsing 
928cb3c676dSjsing 	if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
92940ae7d6bSjoshua 		tls_set_errorx(ctx, TLS_ERROR_INVALID_CONTEXT,
9307a756d37Sjoshua 		    "invalid operation for context");
931cb3c676dSjsing 		rv = -1;
932cb3c676dSjsing 		goto out;
933cb3c676dSjsing 	}
934cb3c676dSjsing 
9355a752462Sjsing 	if (ctx->state & TLS_SSL_NEEDS_SHUTDOWN) {
9369ba095aaSjsing 		ERR_clear_error();
937d29228b9Sjsing 		ssl_ret = SSL_shutdown(ctx->ssl_conn);
9386dce3cf3Sjsing 		if (ssl_ret < 0) {
9396dce3cf3Sjsing 			rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret,
940d29228b9Sjsing 			    "shutdown");
941ab00dbefSbeck 			if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT)
942b71eb829Sbeck 				goto out;
9436dce3cf3Sjsing 		}
9445a752462Sjsing 		ctx->state &= ~TLS_SSL_NEEDS_SHUTDOWN;
945b600beedSjsing 	}
946b600beedSjsing 
947b600beedSjsing 	if (ctx->socket != -1) {
948b600beedSjsing 		if (shutdown(ctx->socket, SHUT_RDWR) != 0) {
9496dce3cf3Sjsing 			if (rv == 0 &&
9506dce3cf3Sjsing 			    errno != ENOTCONN && errno != ECONNRESET) {
9517a756d37Sjoshua 				tls_set_error(ctx, TLS_ERROR_UNKNOWN, "shutdown");
9526dce3cf3Sjsing 				rv = -1;
9536dce3cf3Sjsing 			}
954b600beedSjsing 		}
955b600beedSjsing 		if (close(ctx->socket) != 0) {
9566dce3cf3Sjsing 			if (rv == 0) {
9577a756d37Sjoshua 				tls_set_error(ctx, TLS_ERROR_UNKNOWN, "close");
9586dce3cf3Sjsing 				rv = -1;
9596dce3cf3Sjsing 			}
960b600beedSjsing 		}
961b600beedSjsing 		ctx->socket = -1;
962b600beedSjsing 	}
96339389942Sjsing 
96439389942Sjsing 	if ((ctx->state & TLS_EOF_NO_CLOSE_NOTIFY) != 0) {
9657a756d37Sjoshua 		tls_set_errorx(ctx, TLS_ERROR_UNKNOWN, "EOF without close notify");
96639389942Sjsing 		rv = -1;
96739389942Sjsing 	}
96839389942Sjsing 
969b71eb829Sbeck  out:
97041dd5705Sbeck 	/* Prevent callers from performing incorrect error handling */
971b71eb829Sbeck 	errno = 0;
9726dce3cf3Sjsing 	return (rv);
973b600beedSjsing }
974