xref: /dragonfly/crypto/libressl/tls/tls_config.c (revision de0e0e4d)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: tls_config.c,v 1.65 2022/01/25 21:51:24 eric 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/stat.h>
1972c33676SMaxim Ag 
20f5b1c8a1SJohn Marino #include <ctype.h>
21f5b1c8a1SJohn Marino #include <errno.h>
2272c33676SMaxim Ag #include <fcntl.h>
2372c33676SMaxim Ag #include <pthread.h>
24f5b1c8a1SJohn Marino #include <stdlib.h>
2572c33676SMaxim Ag #include <unistd.h>
26f5b1c8a1SJohn Marino 
27f5b1c8a1SJohn Marino #include <tls.h>
2872c33676SMaxim Ag 
29f5b1c8a1SJohn Marino #include "tls_internal.h"
30f5b1c8a1SJohn Marino 
31cca6fc52SDaniel Fojt static const char default_ca_file[] = TLS_DEFAULT_CA_FILE;
3272c33676SMaxim Ag 
3372c33676SMaxim Ag const char *
tls_default_ca_cert_file(void)3472c33676SMaxim Ag tls_default_ca_cert_file(void)
35f5b1c8a1SJohn Marino {
3672c33676SMaxim Ag 	return default_ca_file;
3772c33676SMaxim Ag }
3872c33676SMaxim Ag 
3972c33676SMaxim Ag int
tls_config_load_file(struct tls_error * error,const char * filetype,const char * filename,char ** buf,size_t * len)4072c33676SMaxim Ag tls_config_load_file(struct tls_error *error, const char *filetype,
4172c33676SMaxim Ag     const char *filename, char **buf, size_t *len)
4272c33676SMaxim Ag {
4372c33676SMaxim Ag 	struct stat st;
4472c33676SMaxim Ag 	int fd = -1;
4572c33676SMaxim Ag 	ssize_t n;
4672c33676SMaxim Ag 
4772c33676SMaxim Ag 	free(*buf);
4872c33676SMaxim Ag 	*buf = NULL;
4972c33676SMaxim Ag 	*len = 0;
5072c33676SMaxim Ag 
5172c33676SMaxim Ag 	if ((fd = open(filename, O_RDONLY)) == -1) {
5272c33676SMaxim Ag 		tls_error_set(error, "failed to open %s file '%s'",
5372c33676SMaxim Ag 		    filetype, filename);
5472c33676SMaxim Ag 		goto err;
5572c33676SMaxim Ag 	}
5672c33676SMaxim Ag 	if (fstat(fd, &st) != 0) {
5772c33676SMaxim Ag 		tls_error_set(error, "failed to stat %s file '%s'",
5872c33676SMaxim Ag 		    filetype, filename);
5972c33676SMaxim Ag 		goto err;
6072c33676SMaxim Ag 	}
6172c33676SMaxim Ag 	if (st.st_size < 0)
6272c33676SMaxim Ag 		goto err;
6372c33676SMaxim Ag 	*len = (size_t)st.st_size;
6472c33676SMaxim Ag 	if ((*buf = malloc(*len)) == NULL) {
6572c33676SMaxim Ag 		tls_error_set(error, "failed to allocate buffer for "
6672c33676SMaxim Ag 		    "%s file", filetype);
6772c33676SMaxim Ag 		goto err;
6872c33676SMaxim Ag 	}
6972c33676SMaxim Ag 	n = read(fd, *buf, *len);
7072c33676SMaxim Ag 	if (n < 0 || (size_t)n != *len) {
7172c33676SMaxim Ag 		tls_error_set(error, "failed to read %s file '%s'",
7272c33676SMaxim Ag 		    filetype, filename);
7372c33676SMaxim Ag 		goto err;
7472c33676SMaxim Ag 	}
7572c33676SMaxim Ag 	close(fd);
76f5b1c8a1SJohn Marino 	return 0;
77f5b1c8a1SJohn Marino 
7872c33676SMaxim Ag  err:
7972c33676SMaxim Ag 	if (fd != -1)
8072c33676SMaxim Ag 		close(fd);
8172c33676SMaxim Ag 	freezero(*buf, *len);
8272c33676SMaxim Ag 	*buf = NULL;
8372c33676SMaxim Ag 	*len = 0;
84f5b1c8a1SJohn Marino 
85f5b1c8a1SJohn Marino 	return -1;
86f5b1c8a1SJohn Marino }
87f5b1c8a1SJohn Marino 
88f5b1c8a1SJohn Marino struct tls_config *
tls_config_new_internal(void)8972c33676SMaxim Ag tls_config_new_internal(void)
90f5b1c8a1SJohn Marino {
91f5b1c8a1SJohn Marino 	struct tls_config *config;
9272c33676SMaxim Ag 	unsigned char sid[TLS_MAX_SESSION_ID_LENGTH];
93f5b1c8a1SJohn Marino 
94f5b1c8a1SJohn Marino 	if ((config = calloc(1, sizeof(*config))) == NULL)
95f5b1c8a1SJohn Marino 		return (NULL);
96f5b1c8a1SJohn Marino 
9772c33676SMaxim Ag 	if (pthread_mutex_init(&config->mutex, NULL) != 0)
9872c33676SMaxim Ag 		goto err;
9972c33676SMaxim Ag 
10072c33676SMaxim Ag 	config->refcount = 1;
10172c33676SMaxim Ag 	config->session_fd = -1;
10272c33676SMaxim Ag 
103f5b1c8a1SJohn Marino 	if ((config->keypair = tls_keypair_new()) == NULL)
104f5b1c8a1SJohn Marino 		goto err;
105f5b1c8a1SJohn Marino 
106f5b1c8a1SJohn Marino 	/*
107f5b1c8a1SJohn Marino 	 * Default configuration.
108f5b1c8a1SJohn Marino 	 */
109f5b1c8a1SJohn Marino 	if (tls_config_set_dheparams(config, "none") != 0)
110f5b1c8a1SJohn Marino 		goto err;
11172c33676SMaxim Ag 	if (tls_config_set_ecdhecurves(config, "default") != 0)
112f5b1c8a1SJohn Marino 		goto err;
113f5b1c8a1SJohn Marino 	if (tls_config_set_ciphers(config, "secure") != 0)
114f5b1c8a1SJohn Marino 		goto err;
115f5b1c8a1SJohn Marino 
11672c33676SMaxim Ag 	if (tls_config_set_protocols(config, TLS_PROTOCOLS_DEFAULT) != 0)
11772c33676SMaxim Ag 		goto err;
11872c33676SMaxim Ag 	if (tls_config_set_verify_depth(config, 6) != 0)
11972c33676SMaxim Ag 		goto err;
12072c33676SMaxim Ag 
12172c33676SMaxim Ag 	/*
12272c33676SMaxim Ag 	 * Set session ID context to a random value.  For the simple case
12372c33676SMaxim Ag 	 * of a single process server this is good enough. For multiprocess
12472c33676SMaxim Ag 	 * servers the session ID needs to be set by the caller.
12572c33676SMaxim Ag 	 */
12672c33676SMaxim Ag 	arc4random_buf(sid, sizeof(sid));
12772c33676SMaxim Ag 	if (tls_config_set_session_id(config, sid, sizeof(sid)) != 0)
12872c33676SMaxim Ag 		goto err;
12972c33676SMaxim Ag 	config->ticket_keyrev = arc4random();
13072c33676SMaxim Ag 	config->ticket_autorekey = 1;
131f5b1c8a1SJohn Marino 
132f5b1c8a1SJohn Marino 	tls_config_prefer_ciphers_server(config);
133f5b1c8a1SJohn Marino 
134f5b1c8a1SJohn Marino 	tls_config_verify(config);
135f5b1c8a1SJohn Marino 
136f5b1c8a1SJohn Marino 	return (config);
137f5b1c8a1SJohn Marino 
138f5b1c8a1SJohn Marino  err:
139f5b1c8a1SJohn Marino 	tls_config_free(config);
140f5b1c8a1SJohn Marino 	return (NULL);
141f5b1c8a1SJohn Marino }
142f5b1c8a1SJohn Marino 
14372c33676SMaxim Ag struct tls_config *
tls_config_new(void)14472c33676SMaxim Ag tls_config_new(void)
14572c33676SMaxim Ag {
14672c33676SMaxim Ag 	if (tls_init() == -1)
14772c33676SMaxim Ag 		return (NULL);
14872c33676SMaxim Ag 
14972c33676SMaxim Ag 	return tls_config_new_internal();
15072c33676SMaxim Ag }
15172c33676SMaxim Ag 
152f5b1c8a1SJohn Marino void
tls_config_free(struct tls_config * config)153f5b1c8a1SJohn Marino tls_config_free(struct tls_config *config)
154f5b1c8a1SJohn Marino {
155f5b1c8a1SJohn Marino 	struct tls_keypair *kp, *nkp;
15672c33676SMaxim Ag 	int refcount;
157f5b1c8a1SJohn Marino 
158f5b1c8a1SJohn Marino 	if (config == NULL)
159f5b1c8a1SJohn Marino 		return;
160f5b1c8a1SJohn Marino 
16172c33676SMaxim Ag 	pthread_mutex_lock(&config->mutex);
16272c33676SMaxim Ag 	refcount = --config->refcount;
16372c33676SMaxim Ag 	pthread_mutex_unlock(&config->mutex);
16472c33676SMaxim Ag 
16572c33676SMaxim Ag 	if (refcount > 0)
16672c33676SMaxim Ag 		return;
16772c33676SMaxim Ag 
168f5b1c8a1SJohn Marino 	for (kp = config->keypair; kp != NULL; kp = nkp) {
169f5b1c8a1SJohn Marino 		nkp = kp->next;
170f5b1c8a1SJohn Marino 		tls_keypair_free(kp);
171f5b1c8a1SJohn Marino 	}
172f5b1c8a1SJohn Marino 
173f5b1c8a1SJohn Marino 	free(config->error.msg);
174f5b1c8a1SJohn Marino 
17572c33676SMaxim Ag 	free(config->alpn);
176f5b1c8a1SJohn Marino 	free((char *)config->ca_mem);
177f5b1c8a1SJohn Marino 	free((char *)config->ca_path);
178f5b1c8a1SJohn Marino 	free((char *)config->ciphers);
17972c33676SMaxim Ag 	free((char *)config->crl_mem);
18072c33676SMaxim Ag 	free(config->ecdhecurves);
181f5b1c8a1SJohn Marino 
182*de0e0e4dSAntonio Huete Jimenez 	pthread_mutex_destroy(&config->mutex);
183*de0e0e4dSAntonio Huete Jimenez 
184f5b1c8a1SJohn Marino 	free(config);
185f5b1c8a1SJohn Marino }
186f5b1c8a1SJohn Marino 
18772c33676SMaxim Ag static void
tls_config_keypair_add(struct tls_config * config,struct tls_keypair * keypair)18872c33676SMaxim Ag tls_config_keypair_add(struct tls_config *config, struct tls_keypair *keypair)
18972c33676SMaxim Ag {
19072c33676SMaxim Ag 	struct tls_keypair *kp;
19172c33676SMaxim Ag 
19272c33676SMaxim Ag 	kp = config->keypair;
19372c33676SMaxim Ag 	while (kp->next != NULL)
19472c33676SMaxim Ag 		kp = kp->next;
19572c33676SMaxim Ag 
19672c33676SMaxim Ag 	kp->next = keypair;
19772c33676SMaxim Ag }
19872c33676SMaxim Ag 
199f5b1c8a1SJohn Marino const char *
tls_config_error(struct tls_config * config)200f5b1c8a1SJohn Marino tls_config_error(struct tls_config *config)
201f5b1c8a1SJohn Marino {
202f5b1c8a1SJohn Marino 	return config->error.msg;
203f5b1c8a1SJohn Marino }
204f5b1c8a1SJohn Marino 
205f5b1c8a1SJohn Marino void
tls_config_clear_keys(struct tls_config * config)206f5b1c8a1SJohn Marino tls_config_clear_keys(struct tls_config *config)
207f5b1c8a1SJohn Marino {
208f5b1c8a1SJohn Marino 	struct tls_keypair *kp;
209f5b1c8a1SJohn Marino 
210f5b1c8a1SJohn Marino 	for (kp = config->keypair; kp != NULL; kp = kp->next)
21172c33676SMaxim Ag 		tls_keypair_clear_key(kp);
212f5b1c8a1SJohn Marino }
213f5b1c8a1SJohn Marino 
214f5b1c8a1SJohn Marino int
tls_config_parse_protocols(uint32_t * protocols,const char * protostr)215f5b1c8a1SJohn Marino tls_config_parse_protocols(uint32_t *protocols, const char *protostr)
216f5b1c8a1SJohn Marino {
217f5b1c8a1SJohn Marino 	uint32_t proto, protos = 0;
218f5b1c8a1SJohn Marino 	char *s, *p, *q;
219f5b1c8a1SJohn Marino 	int negate;
220f5b1c8a1SJohn Marino 
22172c33676SMaxim Ag 	if (protostr == NULL) {
22272c33676SMaxim Ag 		*protocols = TLS_PROTOCOLS_DEFAULT;
22372c33676SMaxim Ag 		return (0);
22472c33676SMaxim Ag 	}
22572c33676SMaxim Ag 
226f5b1c8a1SJohn Marino 	if ((s = strdup(protostr)) == NULL)
227f5b1c8a1SJohn Marino 		return (-1);
228f5b1c8a1SJohn Marino 
229f5b1c8a1SJohn Marino 	q = s;
230f5b1c8a1SJohn Marino 	while ((p = strsep(&q, ",:")) != NULL) {
231f5b1c8a1SJohn Marino 		while (*p == ' ' || *p == '\t')
232f5b1c8a1SJohn Marino 			p++;
233f5b1c8a1SJohn Marino 
234f5b1c8a1SJohn Marino 		negate = 0;
235f5b1c8a1SJohn Marino 		if (*p == '!') {
236f5b1c8a1SJohn Marino 			negate = 1;
237f5b1c8a1SJohn Marino 			p++;
238f5b1c8a1SJohn Marino 		}
239f5b1c8a1SJohn Marino 
240f5b1c8a1SJohn Marino 		if (negate && protos == 0)
241f5b1c8a1SJohn Marino 			protos = TLS_PROTOCOLS_ALL;
242f5b1c8a1SJohn Marino 
243f5b1c8a1SJohn Marino 		proto = 0;
244f5b1c8a1SJohn Marino 		if (strcasecmp(p, "all") == 0 ||
245f5b1c8a1SJohn Marino 		    strcasecmp(p, "legacy") == 0)
246f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOLS_ALL;
247f5b1c8a1SJohn Marino 		else if (strcasecmp(p, "default") == 0 ||
248f5b1c8a1SJohn Marino 		    strcasecmp(p, "secure") == 0)
249f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOLS_DEFAULT;
250f5b1c8a1SJohn Marino 		if (strcasecmp(p, "tlsv1") == 0)
251f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOL_TLSv1;
252f5b1c8a1SJohn Marino 		else if (strcasecmp(p, "tlsv1.0") == 0)
253f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOL_TLSv1_0;
254f5b1c8a1SJohn Marino 		else if (strcasecmp(p, "tlsv1.1") == 0)
255f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOL_TLSv1_1;
256f5b1c8a1SJohn Marino 		else if (strcasecmp(p, "tlsv1.2") == 0)
257f5b1c8a1SJohn Marino 			proto = TLS_PROTOCOL_TLSv1_2;
258cca6fc52SDaniel Fojt 		else if (strcasecmp(p, "tlsv1.3") == 0)
259cca6fc52SDaniel Fojt 			proto = TLS_PROTOCOL_TLSv1_3;
260f5b1c8a1SJohn Marino 
261f5b1c8a1SJohn Marino 		if (proto == 0) {
262f5b1c8a1SJohn Marino 			free(s);
263f5b1c8a1SJohn Marino 			return (-1);
264f5b1c8a1SJohn Marino 		}
265f5b1c8a1SJohn Marino 
266f5b1c8a1SJohn Marino 		if (negate)
267f5b1c8a1SJohn Marino 			protos &= ~proto;
268f5b1c8a1SJohn Marino 		else
269f5b1c8a1SJohn Marino 			protos |= proto;
270f5b1c8a1SJohn Marino 	}
271f5b1c8a1SJohn Marino 
272f5b1c8a1SJohn Marino 	*protocols = protos;
273f5b1c8a1SJohn Marino 
274f5b1c8a1SJohn Marino 	free(s);
275f5b1c8a1SJohn Marino 
276f5b1c8a1SJohn Marino 	return (0);
277f5b1c8a1SJohn Marino }
278f5b1c8a1SJohn Marino 
27972c33676SMaxim Ag static int
tls_config_parse_alpn(struct tls_config * config,const char * alpn,char ** alpn_data,size_t * alpn_len)28072c33676SMaxim Ag tls_config_parse_alpn(struct tls_config *config, const char *alpn,
28172c33676SMaxim Ag     char **alpn_data, size_t *alpn_len)
28272c33676SMaxim Ag {
28372c33676SMaxim Ag 	size_t buf_len, i, len;
28472c33676SMaxim Ag 	char *buf = NULL;
28572c33676SMaxim Ag 	char *s = NULL;
28672c33676SMaxim Ag 	char *p, *q;
28772c33676SMaxim Ag 
28872c33676SMaxim Ag 	free(*alpn_data);
28972c33676SMaxim Ag 	*alpn_data = NULL;
29072c33676SMaxim Ag 	*alpn_len = 0;
29172c33676SMaxim Ag 
29272c33676SMaxim Ag 	if ((buf_len = strlen(alpn) + 1) > 65535) {
29372c33676SMaxim Ag 		tls_config_set_errorx(config, "alpn too large");
29472c33676SMaxim Ag 		goto err;
29572c33676SMaxim Ag 	}
29672c33676SMaxim Ag 
29772c33676SMaxim Ag 	if ((buf = malloc(buf_len)) == NULL) {
29872c33676SMaxim Ag 		tls_config_set_errorx(config, "out of memory");
29972c33676SMaxim Ag 		goto err;
30072c33676SMaxim Ag 	}
30172c33676SMaxim Ag 
30272c33676SMaxim Ag 	if ((s = strdup(alpn)) == NULL) {
30372c33676SMaxim Ag 		tls_config_set_errorx(config, "out of memory");
30472c33676SMaxim Ag 		goto err;
30572c33676SMaxim Ag 	}
30672c33676SMaxim Ag 
30772c33676SMaxim Ag 	i = 0;
30872c33676SMaxim Ag 	q = s;
30972c33676SMaxim Ag 	while ((p = strsep(&q, ",")) != NULL) {
31072c33676SMaxim Ag 		if ((len = strlen(p)) == 0) {
31172c33676SMaxim Ag 			tls_config_set_errorx(config,
31272c33676SMaxim Ag 			    "alpn protocol with zero length");
31372c33676SMaxim Ag 			goto err;
31472c33676SMaxim Ag 		}
31572c33676SMaxim Ag 		if (len > 255) {
31672c33676SMaxim Ag 			tls_config_set_errorx(config,
31772c33676SMaxim Ag 			    "alpn protocol too long");
31872c33676SMaxim Ag 			goto err;
31972c33676SMaxim Ag 		}
32072c33676SMaxim Ag 		buf[i++] = len & 0xff;
32172c33676SMaxim Ag 		memcpy(&buf[i], p, len);
32272c33676SMaxim Ag 		i += len;
32372c33676SMaxim Ag 	}
32472c33676SMaxim Ag 
32572c33676SMaxim Ag 	free(s);
32672c33676SMaxim Ag 
32772c33676SMaxim Ag 	*alpn_data = buf;
32872c33676SMaxim Ag 	*alpn_len = buf_len;
32972c33676SMaxim Ag 
33072c33676SMaxim Ag 	return (0);
33172c33676SMaxim Ag 
33272c33676SMaxim Ag  err:
33372c33676SMaxim Ag 	free(buf);
33472c33676SMaxim Ag 	free(s);
33572c33676SMaxim Ag 
33672c33676SMaxim Ag 	return (-1);
33772c33676SMaxim Ag }
33872c33676SMaxim Ag 
33972c33676SMaxim Ag int
tls_config_set_alpn(struct tls_config * config,const char * alpn)34072c33676SMaxim Ag tls_config_set_alpn(struct tls_config *config, const char *alpn)
34172c33676SMaxim Ag {
34272c33676SMaxim Ag 	return tls_config_parse_alpn(config, alpn, &config->alpn,
34372c33676SMaxim Ag 	    &config->alpn_len);
34472c33676SMaxim Ag }
34572c33676SMaxim Ag 
34672c33676SMaxim Ag static int
tls_config_add_keypair_file_internal(struct tls_config * config,const char * cert_file,const char * key_file,const char * ocsp_file)34772c33676SMaxim Ag tls_config_add_keypair_file_internal(struct tls_config *config,
34872c33676SMaxim Ag     const char *cert_file, const char *key_file, const char *ocsp_file)
34972c33676SMaxim Ag {
35072c33676SMaxim Ag 	struct tls_keypair *keypair;
35172c33676SMaxim Ag 
35272c33676SMaxim Ag 	if ((keypair = tls_keypair_new()) == NULL)
35372c33676SMaxim Ag 		return (-1);
35472c33676SMaxim Ag 	if (tls_keypair_set_cert_file(keypair, &config->error, cert_file) != 0)
35572c33676SMaxim Ag 		goto err;
356*de0e0e4dSAntonio Huete Jimenez 	if (key_file != NULL &&
357*de0e0e4dSAntonio Huete Jimenez 	    tls_keypair_set_key_file(keypair, &config->error, key_file) != 0)
35872c33676SMaxim Ag 		goto err;
35972c33676SMaxim Ag 	if (ocsp_file != NULL &&
36072c33676SMaxim Ag 	    tls_keypair_set_ocsp_staple_file(keypair, &config->error,
36172c33676SMaxim Ag 		ocsp_file) != 0)
36272c33676SMaxim Ag 		goto err;
36372c33676SMaxim Ag 
36472c33676SMaxim Ag 	tls_config_keypair_add(config, keypair);
36572c33676SMaxim Ag 
36672c33676SMaxim Ag 	return (0);
36772c33676SMaxim Ag 
36872c33676SMaxim Ag  err:
36972c33676SMaxim Ag 	tls_keypair_free(keypair);
37072c33676SMaxim Ag 	return (-1);
37172c33676SMaxim Ag }
37272c33676SMaxim Ag 
37372c33676SMaxim Ag static int
tls_config_add_keypair_mem_internal(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len,const uint8_t * staple,size_t staple_len)37472c33676SMaxim Ag tls_config_add_keypair_mem_internal(struct tls_config *config, const uint8_t *cert,
37572c33676SMaxim Ag     size_t cert_len, const uint8_t *key, size_t key_len,
37672c33676SMaxim Ag     const uint8_t *staple, size_t staple_len)
37772c33676SMaxim Ag {
37872c33676SMaxim Ag 	struct tls_keypair *keypair;
37972c33676SMaxim Ag 
38072c33676SMaxim Ag 	if ((keypair = tls_keypair_new()) == NULL)
38172c33676SMaxim Ag 		return (-1);
38272c33676SMaxim Ag 	if (tls_keypair_set_cert_mem(keypair, &config->error, cert, cert_len) != 0)
38372c33676SMaxim Ag 		goto err;
384*de0e0e4dSAntonio Huete Jimenez 	if (key != NULL &&
385*de0e0e4dSAntonio Huete Jimenez 	    tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0)
38672c33676SMaxim Ag 		goto err;
38772c33676SMaxim Ag 	if (staple != NULL &&
38872c33676SMaxim Ag 	    tls_keypair_set_ocsp_staple_mem(keypair, &config->error, staple,
38972c33676SMaxim Ag 		staple_len) != 0)
39072c33676SMaxim Ag 		goto err;
39172c33676SMaxim Ag 
39272c33676SMaxim Ag 	tls_config_keypair_add(config, keypair);
39372c33676SMaxim Ag 
39472c33676SMaxim Ag 	return (0);
39572c33676SMaxim Ag 
39672c33676SMaxim Ag  err:
39772c33676SMaxim Ag 	tls_keypair_free(keypair);
39872c33676SMaxim Ag 	return (-1);
39972c33676SMaxim Ag }
40072c33676SMaxim Ag 
40172c33676SMaxim Ag int
tls_config_add_keypair_mem(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len)40272c33676SMaxim Ag tls_config_add_keypair_mem(struct tls_config *config, const uint8_t *cert,
40372c33676SMaxim Ag     size_t cert_len, const uint8_t *key, size_t key_len)
40472c33676SMaxim Ag {
40572c33676SMaxim Ag 	return tls_config_add_keypair_mem_internal(config, cert, cert_len, key,
40672c33676SMaxim Ag 	    key_len, NULL, 0);
40772c33676SMaxim Ag }
40872c33676SMaxim Ag 
40972c33676SMaxim Ag int
tls_config_add_keypair_file(struct tls_config * config,const char * cert_file,const char * key_file)41072c33676SMaxim Ag tls_config_add_keypair_file(struct tls_config *config,
41172c33676SMaxim Ag     const char *cert_file, const char *key_file)
41272c33676SMaxim Ag {
41372c33676SMaxim Ag 	return tls_config_add_keypair_file_internal(config, cert_file,
41472c33676SMaxim Ag 	    key_file, NULL);
41572c33676SMaxim Ag }
41672c33676SMaxim Ag 
41772c33676SMaxim Ag int
tls_config_add_keypair_ocsp_mem(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len,const uint8_t * staple,size_t staple_len)41872c33676SMaxim Ag tls_config_add_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert,
41972c33676SMaxim Ag     size_t cert_len, const uint8_t *key, size_t key_len, const uint8_t *staple,
42072c33676SMaxim Ag     size_t staple_len)
42172c33676SMaxim Ag {
42272c33676SMaxim Ag 	return tls_config_add_keypair_mem_internal(config, cert, cert_len, key,
42372c33676SMaxim Ag 	    key_len, staple, staple_len);
42472c33676SMaxim Ag }
42572c33676SMaxim Ag 
42672c33676SMaxim Ag int
tls_config_add_keypair_ocsp_file(struct tls_config * config,const char * cert_file,const char * key_file,const char * ocsp_file)42772c33676SMaxim Ag tls_config_add_keypair_ocsp_file(struct tls_config *config,
42872c33676SMaxim Ag     const char *cert_file, const char *key_file, const char *ocsp_file)
42972c33676SMaxim Ag {
43072c33676SMaxim Ag 	return tls_config_add_keypair_file_internal(config, cert_file,
43172c33676SMaxim Ag 	    key_file, ocsp_file);
43272c33676SMaxim Ag }
43372c33676SMaxim Ag 
434f5b1c8a1SJohn Marino int
tls_config_set_ca_file(struct tls_config * config,const char * ca_file)435f5b1c8a1SJohn Marino tls_config_set_ca_file(struct tls_config *config, const char *ca_file)
436f5b1c8a1SJohn Marino {
43772c33676SMaxim Ag 	return tls_config_load_file(&config->error, "CA", ca_file,
43872c33676SMaxim Ag 	    &config->ca_mem, &config->ca_len);
439f5b1c8a1SJohn Marino }
440f5b1c8a1SJohn Marino 
441f5b1c8a1SJohn Marino int
tls_config_set_ca_path(struct tls_config * config,const char * ca_path)442f5b1c8a1SJohn Marino tls_config_set_ca_path(struct tls_config *config, const char *ca_path)
443f5b1c8a1SJohn Marino {
44472c33676SMaxim Ag 	return tls_set_string(&config->ca_path, ca_path);
445f5b1c8a1SJohn Marino }
446f5b1c8a1SJohn Marino 
447f5b1c8a1SJohn Marino int
tls_config_set_ca_mem(struct tls_config * config,const uint8_t * ca,size_t len)448f5b1c8a1SJohn Marino tls_config_set_ca_mem(struct tls_config *config, const uint8_t *ca, size_t len)
449f5b1c8a1SJohn Marino {
45072c33676SMaxim Ag 	return tls_set_mem(&config->ca_mem, &config->ca_len, ca, len);
451f5b1c8a1SJohn Marino }
452f5b1c8a1SJohn Marino 
453f5b1c8a1SJohn Marino int
tls_config_set_cert_file(struct tls_config * config,const char * cert_file)454f5b1c8a1SJohn Marino tls_config_set_cert_file(struct tls_config *config, const char *cert_file)
455f5b1c8a1SJohn Marino {
45672c33676SMaxim Ag 	return tls_keypair_set_cert_file(config->keypair, &config->error,
45772c33676SMaxim Ag 	    cert_file);
458f5b1c8a1SJohn Marino }
459f5b1c8a1SJohn Marino 
460f5b1c8a1SJohn Marino int
tls_config_set_cert_mem(struct tls_config * config,const uint8_t * cert,size_t len)461f5b1c8a1SJohn Marino tls_config_set_cert_mem(struct tls_config *config, const uint8_t *cert,
462f5b1c8a1SJohn Marino     size_t len)
463f5b1c8a1SJohn Marino {
46472c33676SMaxim Ag 	return tls_keypair_set_cert_mem(config->keypair, &config->error,
46572c33676SMaxim Ag 	    cert, len);
466f5b1c8a1SJohn Marino }
467f5b1c8a1SJohn Marino 
468f5b1c8a1SJohn Marino int
tls_config_set_ciphers(struct tls_config * config,const char * ciphers)469f5b1c8a1SJohn Marino tls_config_set_ciphers(struct tls_config *config, const char *ciphers)
470f5b1c8a1SJohn Marino {
471f5b1c8a1SJohn Marino 	SSL_CTX *ssl_ctx = NULL;
472f5b1c8a1SJohn Marino 
473f5b1c8a1SJohn Marino 	if (ciphers == NULL ||
474f5b1c8a1SJohn Marino 	    strcasecmp(ciphers, "default") == 0 ||
475f5b1c8a1SJohn Marino 	    strcasecmp(ciphers, "secure") == 0)
476f5b1c8a1SJohn Marino 		ciphers = TLS_CIPHERS_DEFAULT;
477f5b1c8a1SJohn Marino 	else if (strcasecmp(ciphers, "compat") == 0)
478f5b1c8a1SJohn Marino 		ciphers = TLS_CIPHERS_COMPAT;
479f5b1c8a1SJohn Marino 	else if (strcasecmp(ciphers, "legacy") == 0)
480f5b1c8a1SJohn Marino 		ciphers = TLS_CIPHERS_LEGACY;
481f5b1c8a1SJohn Marino 	else if (strcasecmp(ciphers, "all") == 0 ||
482f5b1c8a1SJohn Marino 	    strcasecmp(ciphers, "insecure") == 0)
483f5b1c8a1SJohn Marino 		ciphers = TLS_CIPHERS_ALL;
484f5b1c8a1SJohn Marino 
485f5b1c8a1SJohn Marino 	if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) {
486f5b1c8a1SJohn Marino 		tls_config_set_errorx(config, "out of memory");
48772c33676SMaxim Ag 		goto err;
488f5b1c8a1SJohn Marino 	}
489f5b1c8a1SJohn Marino 	if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) {
490f5b1c8a1SJohn Marino 		tls_config_set_errorx(config, "no ciphers for '%s'", ciphers);
49172c33676SMaxim Ag 		goto err;
492f5b1c8a1SJohn Marino 	}
493f5b1c8a1SJohn Marino 
494f5b1c8a1SJohn Marino 	SSL_CTX_free(ssl_ctx);
49572c33676SMaxim Ag 	return tls_set_string(&config->ciphers, ciphers);
496f5b1c8a1SJohn Marino 
49772c33676SMaxim Ag  err:
498f5b1c8a1SJohn Marino 	SSL_CTX_free(ssl_ctx);
499f5b1c8a1SJohn Marino 	return -1;
500f5b1c8a1SJohn Marino }
501f5b1c8a1SJohn Marino 
502f5b1c8a1SJohn Marino int
tls_config_set_crl_file(struct tls_config * config,const char * crl_file)50372c33676SMaxim Ag tls_config_set_crl_file(struct tls_config *config, const char *crl_file)
50472c33676SMaxim Ag {
50572c33676SMaxim Ag 	return tls_config_load_file(&config->error, "CRL", crl_file,
50672c33676SMaxim Ag 	    &config->crl_mem, &config->crl_len);
50772c33676SMaxim Ag }
50872c33676SMaxim Ag 
50972c33676SMaxim Ag int
tls_config_set_crl_mem(struct tls_config * config,const uint8_t * crl,size_t len)51072c33676SMaxim Ag tls_config_set_crl_mem(struct tls_config *config, const uint8_t *crl,
51172c33676SMaxim Ag     size_t len)
51272c33676SMaxim Ag {
51372c33676SMaxim Ag 	return tls_set_mem(&config->crl_mem, &config->crl_len, crl, len);
51472c33676SMaxim Ag }
51572c33676SMaxim Ag 
51672c33676SMaxim Ag int
tls_config_set_dheparams(struct tls_config * config,const char * params)517f5b1c8a1SJohn Marino tls_config_set_dheparams(struct tls_config *config, const char *params)
518f5b1c8a1SJohn Marino {
519f5b1c8a1SJohn Marino 	int keylen;
520f5b1c8a1SJohn Marino 
521f5b1c8a1SJohn Marino 	if (params == NULL || strcasecmp(params, "none") == 0)
522f5b1c8a1SJohn Marino 		keylen = 0;
523f5b1c8a1SJohn Marino 	else if (strcasecmp(params, "auto") == 0)
524f5b1c8a1SJohn Marino 		keylen = -1;
525f5b1c8a1SJohn Marino 	else if (strcasecmp(params, "legacy") == 0)
526f5b1c8a1SJohn Marino 		keylen = 1024;
527f5b1c8a1SJohn Marino 	else {
528f5b1c8a1SJohn Marino 		tls_config_set_errorx(config, "invalid dhe param '%s'", params);
529f5b1c8a1SJohn Marino 		return (-1);
530f5b1c8a1SJohn Marino 	}
531f5b1c8a1SJohn Marino 
532f5b1c8a1SJohn Marino 	config->dheparams = keylen;
533f5b1c8a1SJohn Marino 
534f5b1c8a1SJohn Marino 	return (0);
535f5b1c8a1SJohn Marino }
536f5b1c8a1SJohn Marino 
537f5b1c8a1SJohn Marino int
tls_config_set_ecdhecurve(struct tls_config * config,const char * curve)53872c33676SMaxim Ag tls_config_set_ecdhecurve(struct tls_config *config, const char *curve)
539f5b1c8a1SJohn Marino {
54072c33676SMaxim Ag 	if (curve == NULL ||
54172c33676SMaxim Ag 	    strcasecmp(curve, "none") == 0 ||
54272c33676SMaxim Ag 	    strcasecmp(curve, "auto") == 0) {
54372c33676SMaxim Ag 		curve = TLS_ECDHE_CURVES;
54472c33676SMaxim Ag 	} else if (strchr(curve, ',') != NULL || strchr(curve, ':') != NULL) {
54572c33676SMaxim Ag 		tls_config_set_errorx(config, "invalid ecdhe curve '%s'",
54672c33676SMaxim Ag 		    curve);
547f5b1c8a1SJohn Marino 		return (-1);
548f5b1c8a1SJohn Marino 	}
549f5b1c8a1SJohn Marino 
55072c33676SMaxim Ag 	return tls_config_set_ecdhecurves(config, curve);
55172c33676SMaxim Ag }
552f5b1c8a1SJohn Marino 
55372c33676SMaxim Ag int
tls_config_set_ecdhecurves(struct tls_config * config,const char * curves)55472c33676SMaxim Ag tls_config_set_ecdhecurves(struct tls_config *config, const char *curves)
55572c33676SMaxim Ag {
55672c33676SMaxim Ag 	int *curves_list = NULL, *curves_new;
55772c33676SMaxim Ag 	size_t curves_num = 0;
55872c33676SMaxim Ag 	char *cs = NULL;
55972c33676SMaxim Ag 	char *p, *q;
56072c33676SMaxim Ag 	int rv = -1;
56172c33676SMaxim Ag 	int nid;
56272c33676SMaxim Ag 
56372c33676SMaxim Ag 	free(config->ecdhecurves);
56472c33676SMaxim Ag 	config->ecdhecurves = NULL;
56572c33676SMaxim Ag 	config->ecdhecurves_len = 0;
56672c33676SMaxim Ag 
56772c33676SMaxim Ag 	if (curves == NULL || strcasecmp(curves, "default") == 0)
56872c33676SMaxim Ag 		curves = TLS_ECDHE_CURVES;
56972c33676SMaxim Ag 
57072c33676SMaxim Ag 	if ((cs = strdup(curves)) == NULL) {
57172c33676SMaxim Ag 		tls_config_set_errorx(config, "out of memory");
57272c33676SMaxim Ag 		goto err;
57372c33676SMaxim Ag 	}
57472c33676SMaxim Ag 
57572c33676SMaxim Ag 	q = cs;
57672c33676SMaxim Ag 	while ((p = strsep(&q, ",:")) != NULL) {
57772c33676SMaxim Ag 		while (*p == ' ' || *p == '\t')
57872c33676SMaxim Ag 			p++;
57972c33676SMaxim Ag 
58072c33676SMaxim Ag 		nid = OBJ_sn2nid(p);
58172c33676SMaxim Ag 		if (nid == NID_undef)
58272c33676SMaxim Ag 			nid = OBJ_ln2nid(p);
58372c33676SMaxim Ag 		if (nid == NID_undef)
58472c33676SMaxim Ag 			nid = EC_curve_nist2nid(p);
58572c33676SMaxim Ag 		if (nid == NID_undef) {
58672c33676SMaxim Ag 			tls_config_set_errorx(config,
58772c33676SMaxim Ag 			    "invalid ecdhe curve '%s'", p);
58872c33676SMaxim Ag 			goto err;
58972c33676SMaxim Ag 		}
59072c33676SMaxim Ag 
59172c33676SMaxim Ag 		if ((curves_new = reallocarray(curves_list, curves_num + 1,
59272c33676SMaxim Ag 		    sizeof(int))) == NULL) {
59372c33676SMaxim Ag 			tls_config_set_errorx(config, "out of memory");
59472c33676SMaxim Ag 			goto err;
59572c33676SMaxim Ag 		}
59672c33676SMaxim Ag 		curves_list = curves_new;
59772c33676SMaxim Ag 		curves_list[curves_num] = nid;
59872c33676SMaxim Ag 		curves_num++;
59972c33676SMaxim Ag 	}
60072c33676SMaxim Ag 
60172c33676SMaxim Ag 	config->ecdhecurves = curves_list;
60272c33676SMaxim Ag 	config->ecdhecurves_len = curves_num;
60372c33676SMaxim Ag 	curves_list = NULL;
60472c33676SMaxim Ag 
60572c33676SMaxim Ag 	rv = 0;
60672c33676SMaxim Ag 
60772c33676SMaxim Ag  err:
60872c33676SMaxim Ag 	free(cs);
60972c33676SMaxim Ag 	free(curves_list);
61072c33676SMaxim Ag 
61172c33676SMaxim Ag 	return (rv);
612f5b1c8a1SJohn Marino }
613f5b1c8a1SJohn Marino 
614f5b1c8a1SJohn Marino int
tls_config_set_key_file(struct tls_config * config,const char * key_file)615f5b1c8a1SJohn Marino tls_config_set_key_file(struct tls_config *config, const char *key_file)
616f5b1c8a1SJohn Marino {
61772c33676SMaxim Ag 	return tls_keypair_set_key_file(config->keypair, &config->error,
61872c33676SMaxim Ag 	    key_file);
619f5b1c8a1SJohn Marino }
620f5b1c8a1SJohn Marino 
621f5b1c8a1SJohn Marino int
tls_config_set_key_mem(struct tls_config * config,const uint8_t * key,size_t len)622f5b1c8a1SJohn Marino tls_config_set_key_mem(struct tls_config *config, const uint8_t *key,
623f5b1c8a1SJohn Marino     size_t len)
624f5b1c8a1SJohn Marino {
62572c33676SMaxim Ag 	return tls_keypair_set_key_mem(config->keypair, &config->error,
62672c33676SMaxim Ag 	    key, len);
62772c33676SMaxim Ag }
62872c33676SMaxim Ag 
62972c33676SMaxim Ag static int
tls_config_set_keypair_file_internal(struct tls_config * config,const char * cert_file,const char * key_file,const char * ocsp_file)63072c33676SMaxim Ag tls_config_set_keypair_file_internal(struct tls_config *config,
63172c33676SMaxim Ag     const char *cert_file, const char *key_file, const char *ocsp_file)
63272c33676SMaxim Ag {
63372c33676SMaxim Ag 	if (tls_config_set_cert_file(config, cert_file) != 0)
63472c33676SMaxim Ag 		return (-1);
63572c33676SMaxim Ag 	if (tls_config_set_key_file(config, key_file) != 0)
63672c33676SMaxim Ag 		return (-1);
63772c33676SMaxim Ag 	if (ocsp_file != NULL &&
63872c33676SMaxim Ag 	    tls_config_set_ocsp_staple_file(config, ocsp_file) != 0)
63972c33676SMaxim Ag 		return (-1);
64072c33676SMaxim Ag 
64172c33676SMaxim Ag 	return (0);
64272c33676SMaxim Ag }
64372c33676SMaxim Ag 
64472c33676SMaxim Ag static int
tls_config_set_keypair_mem_internal(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len,const uint8_t * staple,size_t staple_len)64572c33676SMaxim Ag tls_config_set_keypair_mem_internal(struct tls_config *config, const uint8_t *cert,
64672c33676SMaxim Ag     size_t cert_len, const uint8_t *key, size_t key_len,
64772c33676SMaxim Ag     const uint8_t *staple, size_t staple_len)
64872c33676SMaxim Ag {
64972c33676SMaxim Ag 	if (tls_config_set_cert_mem(config, cert, cert_len) != 0)
65072c33676SMaxim Ag 		return (-1);
65172c33676SMaxim Ag 	if (tls_config_set_key_mem(config, key, key_len) != 0)
65272c33676SMaxim Ag 		return (-1);
65372c33676SMaxim Ag 	if ((staple != NULL) &&
65472c33676SMaxim Ag 	    (tls_config_set_ocsp_staple_mem(config, staple, staple_len) != 0))
65572c33676SMaxim Ag 		return (-1);
65672c33676SMaxim Ag 
65772c33676SMaxim Ag 	return (0);
658f5b1c8a1SJohn Marino }
659f5b1c8a1SJohn Marino 
660f5b1c8a1SJohn Marino int
tls_config_set_keypair_file(struct tls_config * config,const char * cert_file,const char * key_file)661f5b1c8a1SJohn Marino tls_config_set_keypair_file(struct tls_config *config,
662f5b1c8a1SJohn Marino     const char *cert_file, const char *key_file)
663f5b1c8a1SJohn Marino {
66472c33676SMaxim Ag 	return tls_config_set_keypair_file_internal(config, cert_file, key_file,
66572c33676SMaxim Ag 	    NULL);
666f5b1c8a1SJohn Marino }
667f5b1c8a1SJohn Marino 
668f5b1c8a1SJohn Marino int
tls_config_set_keypair_mem(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len)669f5b1c8a1SJohn Marino tls_config_set_keypair_mem(struct tls_config *config, const uint8_t *cert,
670f5b1c8a1SJohn Marino     size_t cert_len, const uint8_t *key, size_t key_len)
671f5b1c8a1SJohn Marino {
67272c33676SMaxim Ag 	return tls_config_set_keypair_mem_internal(config, cert, cert_len,
67372c33676SMaxim Ag 	    key, key_len, NULL, 0);
67472c33676SMaxim Ag }
67572c33676SMaxim Ag 
67672c33676SMaxim Ag int
tls_config_set_keypair_ocsp_file(struct tls_config * config,const char * cert_file,const char * key_file,const char * ocsp_file)67772c33676SMaxim Ag tls_config_set_keypair_ocsp_file(struct tls_config *config,
67872c33676SMaxim Ag     const char *cert_file, const char *key_file, const char *ocsp_file)
67972c33676SMaxim Ag {
68072c33676SMaxim Ag 	return tls_config_set_keypair_file_internal(config, cert_file, key_file,
68172c33676SMaxim Ag 	    ocsp_file);
68272c33676SMaxim Ag }
68372c33676SMaxim Ag 
68472c33676SMaxim Ag int
tls_config_set_keypair_ocsp_mem(struct tls_config * config,const uint8_t * cert,size_t cert_len,const uint8_t * key,size_t key_len,const uint8_t * staple,size_t staple_len)68572c33676SMaxim Ag tls_config_set_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert,
68672c33676SMaxim Ag     size_t cert_len, const uint8_t *key, size_t key_len,
68772c33676SMaxim Ag     const uint8_t *staple, size_t staple_len)
68872c33676SMaxim Ag {
68972c33676SMaxim Ag 	return tls_config_set_keypair_mem_internal(config, cert, cert_len,
69072c33676SMaxim Ag 	    key, key_len, staple, staple_len);
69172c33676SMaxim Ag }
69272c33676SMaxim Ag 
69372c33676SMaxim Ag 
69472c33676SMaxim Ag int
tls_config_set_protocols(struct tls_config * config,uint32_t protocols)69572c33676SMaxim Ag tls_config_set_protocols(struct tls_config *config, uint32_t protocols)
69672c33676SMaxim Ag {
69772c33676SMaxim Ag 	config->protocols = protocols;
698f5b1c8a1SJohn Marino 
699f5b1c8a1SJohn Marino 	return (0);
700f5b1c8a1SJohn Marino }
701f5b1c8a1SJohn Marino 
70272c33676SMaxim Ag int
tls_config_set_session_fd(struct tls_config * config,int session_fd)70372c33676SMaxim Ag tls_config_set_session_fd(struct tls_config *config, int session_fd)
704f5b1c8a1SJohn Marino {
70572c33676SMaxim Ag 	struct stat sb;
70672c33676SMaxim Ag 	mode_t mugo;
70772c33676SMaxim Ag 
70872c33676SMaxim Ag 	if (session_fd == -1) {
70972c33676SMaxim Ag 		config->session_fd = session_fd;
71072c33676SMaxim Ag 		return (0);
711f5b1c8a1SJohn Marino 	}
712f5b1c8a1SJohn Marino 
71372c33676SMaxim Ag 	if (fstat(session_fd, &sb) == -1) {
71472c33676SMaxim Ag 		tls_config_set_error(config, "failed to stat session file");
71572c33676SMaxim Ag 		return (-1);
71672c33676SMaxim Ag 	}
71772c33676SMaxim Ag 	if (!S_ISREG(sb.st_mode)) {
71872c33676SMaxim Ag 		tls_config_set_errorx(config,
71972c33676SMaxim Ag 		    "session file is not a regular file");
72072c33676SMaxim Ag 		return (-1);
72172c33676SMaxim Ag 	}
72272c33676SMaxim Ag 
72372c33676SMaxim Ag 	if (sb.st_uid != getuid()) {
72472c33676SMaxim Ag 		tls_config_set_errorx(config, "session file has incorrect "
725*de0e0e4dSAntonio Huete Jimenez 		    "owner (uid %u != %u)", sb.st_uid, getuid());
72672c33676SMaxim Ag 		return (-1);
72772c33676SMaxim Ag 	}
72872c33676SMaxim Ag 	mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
72972c33676SMaxim Ag 	if (mugo != (S_IRUSR|S_IWUSR)) {
73072c33676SMaxim Ag 		tls_config_set_errorx(config, "session file has incorrect "
73172c33676SMaxim Ag 		    "permissions (%o != 600)", mugo);
73272c33676SMaxim Ag 		return (-1);
73372c33676SMaxim Ag 	}
73472c33676SMaxim Ag 
73572c33676SMaxim Ag 	config->session_fd = session_fd;
73672c33676SMaxim Ag 
73772c33676SMaxim Ag 	return (0);
73872c33676SMaxim Ag }
73972c33676SMaxim Ag 
74072c33676SMaxim Ag int
tls_config_set_sign_cb(struct tls_config * config,tls_sign_cb cb,void * cb_arg)741*de0e0e4dSAntonio Huete Jimenez tls_config_set_sign_cb(struct tls_config *config, tls_sign_cb cb, void *cb_arg)
742*de0e0e4dSAntonio Huete Jimenez {
743*de0e0e4dSAntonio Huete Jimenez 	config->use_fake_private_key = 1;
744*de0e0e4dSAntonio Huete Jimenez 	config->skip_private_key_check = 1;
745*de0e0e4dSAntonio Huete Jimenez 	config->sign_cb = cb;
746*de0e0e4dSAntonio Huete Jimenez 	config->sign_cb_arg = cb_arg;
747*de0e0e4dSAntonio Huete Jimenez 
748*de0e0e4dSAntonio Huete Jimenez 	return (0);
749*de0e0e4dSAntonio Huete Jimenez }
750*de0e0e4dSAntonio Huete Jimenez 
751*de0e0e4dSAntonio Huete Jimenez int
tls_config_set_verify_depth(struct tls_config * config,int verify_depth)752f5b1c8a1SJohn Marino tls_config_set_verify_depth(struct tls_config *config, int verify_depth)
753f5b1c8a1SJohn Marino {
754f5b1c8a1SJohn Marino 	config->verify_depth = verify_depth;
75572c33676SMaxim Ag 
75672c33676SMaxim Ag 	return (0);
757f5b1c8a1SJohn Marino }
758f5b1c8a1SJohn Marino 
759f5b1c8a1SJohn Marino void
tls_config_prefer_ciphers_client(struct tls_config * config)760f5b1c8a1SJohn Marino tls_config_prefer_ciphers_client(struct tls_config *config)
761f5b1c8a1SJohn Marino {
762f5b1c8a1SJohn Marino 	config->ciphers_server = 0;
763f5b1c8a1SJohn Marino }
764f5b1c8a1SJohn Marino 
765f5b1c8a1SJohn Marino void
tls_config_prefer_ciphers_server(struct tls_config * config)766f5b1c8a1SJohn Marino tls_config_prefer_ciphers_server(struct tls_config *config)
767f5b1c8a1SJohn Marino {
768f5b1c8a1SJohn Marino 	config->ciphers_server = 1;
769f5b1c8a1SJohn Marino }
770f5b1c8a1SJohn Marino 
771f5b1c8a1SJohn Marino void
tls_config_insecure_noverifycert(struct tls_config * config)772f5b1c8a1SJohn Marino tls_config_insecure_noverifycert(struct tls_config *config)
773f5b1c8a1SJohn Marino {
774f5b1c8a1SJohn Marino 	config->verify_cert = 0;
775f5b1c8a1SJohn Marino }
776f5b1c8a1SJohn Marino 
777f5b1c8a1SJohn Marino void
tls_config_insecure_noverifyname(struct tls_config * config)778f5b1c8a1SJohn Marino tls_config_insecure_noverifyname(struct tls_config *config)
779f5b1c8a1SJohn Marino {
780f5b1c8a1SJohn Marino 	config->verify_name = 0;
781f5b1c8a1SJohn Marino }
782f5b1c8a1SJohn Marino 
783f5b1c8a1SJohn Marino void
tls_config_insecure_noverifytime(struct tls_config * config)784f5b1c8a1SJohn Marino tls_config_insecure_noverifytime(struct tls_config *config)
785f5b1c8a1SJohn Marino {
786f5b1c8a1SJohn Marino 	config->verify_time = 0;
787f5b1c8a1SJohn Marino }
788f5b1c8a1SJohn Marino 
789f5b1c8a1SJohn Marino void
tls_config_verify(struct tls_config * config)790f5b1c8a1SJohn Marino tls_config_verify(struct tls_config *config)
791f5b1c8a1SJohn Marino {
792f5b1c8a1SJohn Marino 	config->verify_cert = 1;
793f5b1c8a1SJohn Marino 	config->verify_name = 1;
794f5b1c8a1SJohn Marino 	config->verify_time = 1;
795f5b1c8a1SJohn Marino }
796f5b1c8a1SJohn Marino 
797f5b1c8a1SJohn Marino void
tls_config_ocsp_require_stapling(struct tls_config * config)79872c33676SMaxim Ag tls_config_ocsp_require_stapling(struct tls_config *config)
79972c33676SMaxim Ag {
80072c33676SMaxim Ag 	config->ocsp_require_stapling = 1;
80172c33676SMaxim Ag }
80272c33676SMaxim Ag 
80372c33676SMaxim Ag void
tls_config_verify_client(struct tls_config * config)804f5b1c8a1SJohn Marino tls_config_verify_client(struct tls_config *config)
805f5b1c8a1SJohn Marino {
806f5b1c8a1SJohn Marino 	config->verify_client = 1;
807f5b1c8a1SJohn Marino }
808f5b1c8a1SJohn Marino 
809f5b1c8a1SJohn Marino void
tls_config_verify_client_optional(struct tls_config * config)810f5b1c8a1SJohn Marino tls_config_verify_client_optional(struct tls_config *config)
811f5b1c8a1SJohn Marino {
812f5b1c8a1SJohn Marino 	config->verify_client = 2;
813f5b1c8a1SJohn Marino }
81472c33676SMaxim Ag 
81572c33676SMaxim Ag void
tls_config_skip_private_key_check(struct tls_config * config)81672c33676SMaxim Ag tls_config_skip_private_key_check(struct tls_config *config)
81772c33676SMaxim Ag {
81872c33676SMaxim Ag 	config->skip_private_key_check = 1;
81972c33676SMaxim Ag }
82072c33676SMaxim Ag 
821*de0e0e4dSAntonio Huete Jimenez void
tls_config_use_fake_private_key(struct tls_config * config)822*de0e0e4dSAntonio Huete Jimenez tls_config_use_fake_private_key(struct tls_config *config)
823*de0e0e4dSAntonio Huete Jimenez {
824*de0e0e4dSAntonio Huete Jimenez 	config->use_fake_private_key = 1;
825*de0e0e4dSAntonio Huete Jimenez 	config->skip_private_key_check = 1;
826*de0e0e4dSAntonio Huete Jimenez }
827*de0e0e4dSAntonio Huete Jimenez 
82872c33676SMaxim Ag int
tls_config_set_ocsp_staple_file(struct tls_config * config,const char * staple_file)82972c33676SMaxim Ag tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file)
83072c33676SMaxim Ag {
83172c33676SMaxim Ag 	return tls_keypair_set_ocsp_staple_file(config->keypair, &config->error,
83272c33676SMaxim Ag 	    staple_file);
83372c33676SMaxim Ag }
83472c33676SMaxim Ag 
83572c33676SMaxim Ag int
tls_config_set_ocsp_staple_mem(struct tls_config * config,const uint8_t * staple,size_t len)83672c33676SMaxim Ag tls_config_set_ocsp_staple_mem(struct tls_config *config, const uint8_t *staple,
83772c33676SMaxim Ag     size_t len)
83872c33676SMaxim Ag {
83972c33676SMaxim Ag 	return tls_keypair_set_ocsp_staple_mem(config->keypair, &config->error,
84072c33676SMaxim Ag 	    staple, len);
84172c33676SMaxim Ag }
84272c33676SMaxim Ag 
84372c33676SMaxim Ag int
tls_config_set_session_id(struct tls_config * config,const unsigned char * session_id,size_t len)84472c33676SMaxim Ag tls_config_set_session_id(struct tls_config *config,
84572c33676SMaxim Ag     const unsigned char *session_id, size_t len)
84672c33676SMaxim Ag {
84772c33676SMaxim Ag 	if (len > TLS_MAX_SESSION_ID_LENGTH) {
84872c33676SMaxim Ag 		tls_config_set_errorx(config, "session ID too large");
84972c33676SMaxim Ag 		return (-1);
85072c33676SMaxim Ag 	}
85172c33676SMaxim Ag 	memset(config->session_id, 0, sizeof(config->session_id));
85272c33676SMaxim Ag 	memcpy(config->session_id, session_id, len);
85372c33676SMaxim Ag 	return (0);
85472c33676SMaxim Ag }
85572c33676SMaxim Ag 
85672c33676SMaxim Ag int
tls_config_set_session_lifetime(struct tls_config * config,int lifetime)85772c33676SMaxim Ag tls_config_set_session_lifetime(struct tls_config *config, int lifetime)
85872c33676SMaxim Ag {
85972c33676SMaxim Ag 	if (lifetime > TLS_MAX_SESSION_TIMEOUT) {
86072c33676SMaxim Ag 		tls_config_set_errorx(config, "session lifetime too large");
86172c33676SMaxim Ag 		return (-1);
86272c33676SMaxim Ag 	}
86372c33676SMaxim Ag 	if (lifetime != 0 && lifetime < TLS_MIN_SESSION_TIMEOUT) {
86472c33676SMaxim Ag 		tls_config_set_errorx(config, "session lifetime too small");
86572c33676SMaxim Ag 		return (-1);
86672c33676SMaxim Ag 	}
86772c33676SMaxim Ag 
86872c33676SMaxim Ag 	config->session_lifetime = lifetime;
86972c33676SMaxim Ag 	return (0);
87072c33676SMaxim Ag }
87172c33676SMaxim Ag 
87272c33676SMaxim Ag int
tls_config_add_ticket_key(struct tls_config * config,uint32_t keyrev,unsigned char * key,size_t keylen)87372c33676SMaxim Ag tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev,
87472c33676SMaxim Ag     unsigned char *key, size_t keylen)
87572c33676SMaxim Ag {
87672c33676SMaxim Ag 	struct tls_ticket_key newkey;
87772c33676SMaxim Ag 	int i;
87872c33676SMaxim Ag 
87972c33676SMaxim Ag 	if (TLS_TICKET_KEY_SIZE != keylen ||
88072c33676SMaxim Ag 	    sizeof(newkey.aes_key) + sizeof(newkey.hmac_key) > keylen) {
88172c33676SMaxim Ag 		tls_config_set_errorx(config,
88272c33676SMaxim Ag 		    "wrong amount of ticket key data");
88372c33676SMaxim Ag 		return (-1);
88472c33676SMaxim Ag 	}
88572c33676SMaxim Ag 
88672c33676SMaxim Ag 	keyrev = htonl(keyrev);
88772c33676SMaxim Ag 	memset(&newkey, 0, sizeof(newkey));
88872c33676SMaxim Ag 	memcpy(newkey.key_name, &keyrev, sizeof(keyrev));
88972c33676SMaxim Ag 	memcpy(newkey.aes_key, key, sizeof(newkey.aes_key));
89072c33676SMaxim Ag 	memcpy(newkey.hmac_key, key + sizeof(newkey.aes_key),
89172c33676SMaxim Ag 	    sizeof(newkey.hmac_key));
89272c33676SMaxim Ag 	newkey.time = time(NULL);
89372c33676SMaxim Ag 
89472c33676SMaxim Ag 	for (i = 0; i < TLS_NUM_TICKETS; i++) {
89572c33676SMaxim Ag 		struct tls_ticket_key *tk = &config->ticket_keys[i];
89672c33676SMaxim Ag 		if (memcmp(newkey.key_name, tk->key_name,
89772c33676SMaxim Ag 		    sizeof(tk->key_name)) != 0)
89872c33676SMaxim Ag 			continue;
89972c33676SMaxim Ag 
90072c33676SMaxim Ag 		/* allow re-entry of most recent key */
90172c33676SMaxim Ag 		if (i == 0 && memcmp(newkey.aes_key, tk->aes_key,
90272c33676SMaxim Ag 		    sizeof(tk->aes_key)) == 0 && memcmp(newkey.hmac_key,
90372c33676SMaxim Ag 		    tk->hmac_key, sizeof(tk->hmac_key)) == 0)
90472c33676SMaxim Ag 			return (0);
90572c33676SMaxim Ag 		tls_config_set_errorx(config, "ticket key already present");
90672c33676SMaxim Ag 		return (-1);
90772c33676SMaxim Ag 	}
90872c33676SMaxim Ag 
90972c33676SMaxim Ag 	memmove(&config->ticket_keys[1], &config->ticket_keys[0],
91072c33676SMaxim Ag 	    sizeof(config->ticket_keys) - sizeof(config->ticket_keys[0]));
91172c33676SMaxim Ag 	config->ticket_keys[0] = newkey;
91272c33676SMaxim Ag 
91372c33676SMaxim Ag 	config->ticket_autorekey = 0;
91472c33676SMaxim Ag 
91572c33676SMaxim Ag 	return (0);
91672c33676SMaxim Ag }
91772c33676SMaxim Ag 
91872c33676SMaxim Ag int
tls_config_ticket_autorekey(struct tls_config * config)91972c33676SMaxim Ag tls_config_ticket_autorekey(struct tls_config *config)
92072c33676SMaxim Ag {
92172c33676SMaxim Ag 	unsigned char key[TLS_TICKET_KEY_SIZE];
92272c33676SMaxim Ag 	int rv;
92372c33676SMaxim Ag 
92472c33676SMaxim Ag 	arc4random_buf(key, sizeof(key));
92572c33676SMaxim Ag 	rv = tls_config_add_ticket_key(config, config->ticket_keyrev++, key,
92672c33676SMaxim Ag 	    sizeof(key));
92772c33676SMaxim Ag 	config->ticket_autorekey = 1;
92872c33676SMaxim Ag 	return (rv);
92972c33676SMaxim Ag }
930