1*6a16e2b3Stb /* $OpenBSD: tls_config.c,v 1.71 2024/08/02 15:00:01 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 1803ce4948Sjsing #include <sys/stat.h> 1903ce4948Sjsing 20729a1688Sjsing #include <ctype.h> 21b600beedSjsing #include <errno.h> 2203ce4948Sjsing #include <fcntl.h> 23bebb943aSjsing #include <pthread.h> 24b600beedSjsing #include <stdlib.h> 25e6d77be9Sop #include <string.h> 2603ce4948Sjsing #include <unistd.h> 27b600beedSjsing 28b600beedSjsing #include <tls.h> 29bb4cb1b0Sjsing 30b600beedSjsing #include "tls_internal.h" 31b600beedSjsing 3215dff5baSbeck static const char default_ca_file[] = TLS_DEFAULT_CA_FILE; 33f6b75673Stedu 34f6b75673Stedu const char * 35f6b75673Stedu tls_default_ca_cert_file(void) 36f6b75673Stedu { 37f6b75673Stedu return default_ca_file; 38f6b75673Stedu } 39f6b75673Stedu 4003ce4948Sjsing int 4103ce4948Sjsing tls_config_load_file(struct tls_error *error, const char *filetype, 4203ce4948Sjsing const char *filename, char **buf, size_t *len) 4303ce4948Sjsing { 4403ce4948Sjsing struct stat st; 4503ce4948Sjsing int fd = -1; 463a0b22e9Sjsing ssize_t n; 4703ce4948Sjsing 4803ce4948Sjsing free(*buf); 4903ce4948Sjsing *buf = NULL; 5003ce4948Sjsing *len = 0; 5103ce4948Sjsing 5203ce4948Sjsing if ((fd = open(filename, O_RDONLY)) == -1) { 537a756d37Sjoshua tls_error_set(error, TLS_ERROR_UNKNOWN, 547a756d37Sjoshua "failed to open %s file '%s'", 5503ce4948Sjsing filetype, filename); 567add217bSjsing goto err; 5703ce4948Sjsing } 5803ce4948Sjsing if (fstat(fd, &st) != 0) { 597a756d37Sjoshua tls_error_set(error, TLS_ERROR_UNKNOWN, 607a756d37Sjoshua "failed to stat %s file '%s'", 6103ce4948Sjsing filetype, filename); 627add217bSjsing goto err; 6303ce4948Sjsing } 643a0b22e9Sjsing if (st.st_size < 0) 657add217bSjsing goto err; 6603ce4948Sjsing *len = (size_t)st.st_size; 6703ce4948Sjsing if ((*buf = malloc(*len)) == NULL) { 687a756d37Sjoshua tls_error_set(error, TLS_ERROR_UNKNOWN, 697a756d37Sjoshua "failed to allocate buffer for %s file", 707a756d37Sjoshua filetype); 717add217bSjsing goto err; 7203ce4948Sjsing } 733a0b22e9Sjsing n = read(fd, *buf, *len); 743a0b22e9Sjsing if (n < 0 || (size_t)n != *len) { 757a756d37Sjoshua tls_error_set(error, TLS_ERROR_UNKNOWN, 767a756d37Sjoshua "failed to read %s file '%s'", 7703ce4948Sjsing filetype, filename); 787add217bSjsing goto err; 7903ce4948Sjsing } 8003ce4948Sjsing close(fd); 8103ce4948Sjsing return 0; 8203ce4948Sjsing 837add217bSjsing err: 8403ce4948Sjsing if (fd != -1) 8503ce4948Sjsing close(fd); 867de8a684Sderaadt freezero(*buf, *len); 8703ce4948Sjsing *buf = NULL; 8803ce4948Sjsing *len = 0; 8903ce4948Sjsing 9003ce4948Sjsing return -1; 9103ce4948Sjsing } 9203ce4948Sjsing 93b600beedSjsing struct tls_config * 94b9573a74Sjsing tls_config_new_internal(void) 95b600beedSjsing { 96b600beedSjsing struct tls_config *config; 9747c43cfeSclaudio unsigned char sid[TLS_MAX_SESSION_ID_LENGTH]; 98b600beedSjsing 99b600beedSjsing if ((config = calloc(1, sizeof(*config))) == NULL) 100b600beedSjsing return (NULL); 101b600beedSjsing 102d7e2296cSjsing if (pthread_mutex_init(&config->mutex, NULL) != 0) 1031fe9fea1Sjsing goto err; 1041fe9fea1Sjsing 10588c10dabSjsing config->refcount = 1; 1060dd084b9Sjsing config->session_fd = -1; 10788c10dabSjsing 108d7e2296cSjsing if ((config->keypair = tls_keypair_new()) == NULL) 109d7e2296cSjsing goto err; 110d7e2296cSjsing 111b600beedSjsing /* 112b600beedSjsing * Default configuration. 113b600beedSjsing */ 1141d9579efSjsing if (tls_config_set_dheparams(config, "none") != 0) 1151d9579efSjsing goto err; 1164896de1eSjsing if (tls_config_set_ecdhecurves(config, "default") != 0) 1171d9579efSjsing goto err; 1181d9579efSjsing if (tls_config_set_ciphers(config, "secure") != 0) 1191d9579efSjsing goto err; 1201d9579efSjsing 1212b50121aSjsing if (tls_config_set_protocols(config, TLS_PROTOCOLS_DEFAULT) != 0) 1222b50121aSjsing goto err; 1232b50121aSjsing if (tls_config_set_verify_depth(config, 6) != 0) 1242b50121aSjsing goto err; 125b600beedSjsing 12647c43cfeSclaudio /* 12747c43cfeSclaudio * Set session ID context to a random value. For the simple case 12847c43cfeSclaudio * of a single process server this is good enough. For multiprocess 12947c43cfeSclaudio * servers the session ID needs to be set by the caller. 13047c43cfeSclaudio */ 13147c43cfeSclaudio arc4random_buf(sid, sizeof(sid)); 13247c43cfeSclaudio if (tls_config_set_session_id(config, sid, sizeof(sid)) != 0) 13347c43cfeSclaudio goto err; 13447c43cfeSclaudio config->ticket_keyrev = arc4random(); 13547c43cfeSclaudio config->ticket_autorekey = 1; 13647c43cfeSclaudio 137c57e6ec0Sjsing tls_config_prefer_ciphers_server(config); 138c57e6ec0Sjsing 139b600beedSjsing tls_config_verify(config); 140b600beedSjsing 141b600beedSjsing return (config); 1421d9579efSjsing 1431d9579efSjsing err: 1441d9579efSjsing tls_config_free(config); 1451d9579efSjsing return (NULL); 146b600beedSjsing } 147b600beedSjsing 148b9573a74Sjsing struct tls_config * 149b9573a74Sjsing tls_config_new(void) 150b9573a74Sjsing { 151b9573a74Sjsing if (tls_init() == -1) 152b9573a74Sjsing return (NULL); 153b9573a74Sjsing 154b9573a74Sjsing return tls_config_new_internal(); 155b9573a74Sjsing } 156b9573a74Sjsing 157b600beedSjsing void 158b600beedSjsing tls_config_free(struct tls_config *config) 159b600beedSjsing { 1601fe9fea1Sjsing struct tls_keypair *kp, *nkp; 161bebb943aSjsing int refcount; 1621fe9fea1Sjsing 163b600beedSjsing if (config == NULL) 164b600beedSjsing return; 165b600beedSjsing 166bebb943aSjsing pthread_mutex_lock(&config->mutex); 167bebb943aSjsing refcount = --config->refcount; 168bebb943aSjsing pthread_mutex_unlock(&config->mutex); 169bebb943aSjsing 170bebb943aSjsing if (refcount > 0) 17188c10dabSjsing return; 17288c10dabSjsing 1731fe9fea1Sjsing for (kp = config->keypair; kp != NULL; kp = nkp) { 1741fe9fea1Sjsing nkp = kp->next; 1751fe9fea1Sjsing tls_keypair_free(kp); 1761fe9fea1Sjsing } 177b600beedSjsing 178a88e9e95Sjsing free(config->error.msg); 179a88e9e95Sjsing 180183da8c6Sjsing free(config->alpn); 1812c79fa3fSjsing free((char *)config->ca_mem); 182b600beedSjsing free((char *)config->ca_path); 183b600beedSjsing free((char *)config->ciphers); 18480bc881dSjsing free((char *)config->crl_mem); 1854896de1eSjsing free(config->ecdhecurves); 186b600beedSjsing 187b900ccc5Sbcook pthread_mutex_destroy(&config->mutex); 188b900ccc5Sbcook 189b600beedSjsing free(config); 190b600beedSjsing } 191b600beedSjsing 19255272e79Sjsing static void 19355272e79Sjsing tls_config_keypair_add(struct tls_config *config, struct tls_keypair *keypair) 19455272e79Sjsing { 19555272e79Sjsing struct tls_keypair *kp; 19655272e79Sjsing 19755272e79Sjsing kp = config->keypair; 19855272e79Sjsing while (kp->next != NULL) 19955272e79Sjsing kp = kp->next; 20055272e79Sjsing 20155272e79Sjsing kp->next = keypair; 20255272e79Sjsing } 20355272e79Sjsing 204a88e9e95Sjsing const char * 205a88e9e95Sjsing tls_config_error(struct tls_config *config) 206a88e9e95Sjsing { 207a88e9e95Sjsing return config->error.msg; 208a88e9e95Sjsing } 209a88e9e95Sjsing 2107a756d37Sjoshua int 2117a756d37Sjoshua tls_config_error_code(struct tls_config *config) 2127a756d37Sjoshua { 2137a756d37Sjoshua return config->error.code; 2147a756d37Sjoshua } 2157a756d37Sjoshua 216b600beedSjsing void 217b600beedSjsing tls_config_clear_keys(struct tls_config *config) 218b600beedSjsing { 2191fe9fea1Sjsing struct tls_keypair *kp; 2201fe9fea1Sjsing 2211fe9fea1Sjsing for (kp = config->keypair; kp != NULL; kp = kp->next) 222b3064b8aSjsing tls_keypair_clear_key(kp); 223b600beedSjsing } 224b600beedSjsing 225b600beedSjsing int 226729a1688Sjsing tls_config_parse_protocols(uint32_t *protocols, const char *protostr) 227729a1688Sjsing { 228729a1688Sjsing uint32_t proto, protos = 0; 229729a1688Sjsing char *s, *p, *q; 230729a1688Sjsing int negate; 231729a1688Sjsing 232568004a5Sjsing if (protostr == NULL) { 233568004a5Sjsing *protocols = TLS_PROTOCOLS_DEFAULT; 234568004a5Sjsing return (0); 235568004a5Sjsing } 236c68c7b49Sjsing 237729a1688Sjsing if ((s = strdup(protostr)) == NULL) 238729a1688Sjsing return (-1); 239729a1688Sjsing 240729a1688Sjsing q = s; 241729a1688Sjsing while ((p = strsep(&q, ",:")) != NULL) { 242729a1688Sjsing while (*p == ' ' || *p == '\t') 243729a1688Sjsing p++; 244729a1688Sjsing 245729a1688Sjsing negate = 0; 246729a1688Sjsing if (*p == '!') { 247729a1688Sjsing negate = 1; 248729a1688Sjsing p++; 249729a1688Sjsing } 250729a1688Sjsing 251729a1688Sjsing if (negate && protos == 0) 252729a1688Sjsing protos = TLS_PROTOCOLS_ALL; 253729a1688Sjsing 254729a1688Sjsing proto = 0; 255729a1688Sjsing if (strcasecmp(p, "all") == 0 || 256729a1688Sjsing strcasecmp(p, "legacy") == 0) 257729a1688Sjsing proto = TLS_PROTOCOLS_ALL; 258729a1688Sjsing else if (strcasecmp(p, "default") == 0 || 259729a1688Sjsing strcasecmp(p, "secure") == 0) 260729a1688Sjsing proto = TLS_PROTOCOLS_DEFAULT; 261729a1688Sjsing if (strcasecmp(p, "tlsv1") == 0) 262729a1688Sjsing proto = TLS_PROTOCOL_TLSv1; 263729a1688Sjsing else if (strcasecmp(p, "tlsv1.0") == 0) 264*6a16e2b3Stb proto = TLS_PROTOCOL_TLSv1_0; 265729a1688Sjsing else if (strcasecmp(p, "tlsv1.1") == 0) 266*6a16e2b3Stb proto = TLS_PROTOCOL_TLSv1_1; 267729a1688Sjsing else if (strcasecmp(p, "tlsv1.2") == 0) 268729a1688Sjsing proto = TLS_PROTOCOL_TLSv1_2; 2694c479435Sjsing else if (strcasecmp(p, "tlsv1.3") == 0) 2704c479435Sjsing proto = TLS_PROTOCOL_TLSv1_3; 271729a1688Sjsing 272729a1688Sjsing if (proto == 0) { 273729a1688Sjsing free(s); 274729a1688Sjsing return (-1); 275729a1688Sjsing } 276729a1688Sjsing 277729a1688Sjsing if (negate) 278729a1688Sjsing protos &= ~proto; 279729a1688Sjsing else 280729a1688Sjsing protos |= proto; 281729a1688Sjsing } 282729a1688Sjsing 283729a1688Sjsing *protocols = protos; 284729a1688Sjsing 285729a1688Sjsing free(s); 286729a1688Sjsing 287729a1688Sjsing return (0); 288729a1688Sjsing } 289729a1688Sjsing 290183da8c6Sjsing static int 291183da8c6Sjsing tls_config_parse_alpn(struct tls_config *config, const char *alpn, 292183da8c6Sjsing char **alpn_data, size_t *alpn_len) 293183da8c6Sjsing { 294183da8c6Sjsing size_t buf_len, i, len; 295183da8c6Sjsing char *buf = NULL; 296183da8c6Sjsing char *s = NULL; 297183da8c6Sjsing char *p, *q; 298183da8c6Sjsing 29985212ddeSjsing free(*alpn_data); 30085212ddeSjsing *alpn_data = NULL; 30185212ddeSjsing *alpn_len = 0; 30285212ddeSjsing 303183da8c6Sjsing if ((buf_len = strlen(alpn) + 1) > 65535) { 3042d60058eSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 3052d60058eSjoshua "alpn too large"); 306183da8c6Sjsing goto err; 307183da8c6Sjsing } 308183da8c6Sjsing 309183da8c6Sjsing if ((buf = malloc(buf_len)) == NULL) { 3107a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, 3117a756d37Sjoshua "out of memory"); 312183da8c6Sjsing goto err; 313183da8c6Sjsing } 314183da8c6Sjsing 315183da8c6Sjsing if ((s = strdup(alpn)) == NULL) { 3167a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, 3177a756d37Sjoshua "out of memory"); 318183da8c6Sjsing goto err; 319183da8c6Sjsing } 320183da8c6Sjsing 321183da8c6Sjsing i = 0; 322183da8c6Sjsing q = s; 323183da8c6Sjsing while ((p = strsep(&q, ",")) != NULL) { 324183da8c6Sjsing if ((len = strlen(p)) == 0) { 3252b31d1bdSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 326183da8c6Sjsing "alpn protocol with zero length"); 327183da8c6Sjsing goto err; 328183da8c6Sjsing } 329183da8c6Sjsing if (len > 255) { 3302b31d1bdSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 331183da8c6Sjsing "alpn protocol too long"); 332183da8c6Sjsing goto err; 333183da8c6Sjsing } 334183da8c6Sjsing buf[i++] = len & 0xff; 335183da8c6Sjsing memcpy(&buf[i], p, len); 336183da8c6Sjsing i += len; 337183da8c6Sjsing } 338183da8c6Sjsing 339183da8c6Sjsing free(s); 340183da8c6Sjsing 341183da8c6Sjsing *alpn_data = buf; 342183da8c6Sjsing *alpn_len = buf_len; 343183da8c6Sjsing 344183da8c6Sjsing return (0); 345183da8c6Sjsing 346183da8c6Sjsing err: 347183da8c6Sjsing free(buf); 348183da8c6Sjsing free(s); 349183da8c6Sjsing 350183da8c6Sjsing return (-1); 351183da8c6Sjsing } 352183da8c6Sjsing 353183da8c6Sjsing int 354183da8c6Sjsing tls_config_set_alpn(struct tls_config *config, const char *alpn) 355183da8c6Sjsing { 356183da8c6Sjsing return tls_config_parse_alpn(config, alpn, &config->alpn, 357183da8c6Sjsing &config->alpn_len); 358183da8c6Sjsing } 359183da8c6Sjsing 360ef012c23Sbeck static int 361ef012c23Sbeck tls_config_add_keypair_file_internal(struct tls_config *config, 362ef012c23Sbeck const char *cert_file, const char *key_file, const char *ocsp_file) 36355272e79Sjsing { 36455272e79Sjsing struct tls_keypair *keypair; 36555272e79Sjsing 36655272e79Sjsing if ((keypair = tls_keypair_new()) == NULL) 36755272e79Sjsing return (-1); 36855272e79Sjsing if (tls_keypair_set_cert_file(keypair, &config->error, cert_file) != 0) 36955272e79Sjsing goto err; 37015339a8cSeric if (key_file != NULL && 37115339a8cSeric tls_keypair_set_key_file(keypair, &config->error, key_file) != 0) 37255272e79Sjsing goto err; 373ef012c23Sbeck if (ocsp_file != NULL && 374ef012c23Sbeck tls_keypair_set_ocsp_staple_file(keypair, &config->error, 375ef012c23Sbeck ocsp_file) != 0) 376ef012c23Sbeck goto err; 377ef012c23Sbeck 378ef012c23Sbeck tls_config_keypair_add(config, keypair); 379ef012c23Sbeck 380ef012c23Sbeck return (0); 381ef012c23Sbeck 382ef012c23Sbeck err: 383ef012c23Sbeck tls_keypair_free(keypair); 384ef012c23Sbeck return (-1); 385ef012c23Sbeck } 386ef012c23Sbeck 387ef012c23Sbeck static int 388ef012c23Sbeck tls_config_add_keypair_mem_internal(struct tls_config *config, const uint8_t *cert, 389ef012c23Sbeck size_t cert_len, const uint8_t *key, size_t key_len, 390ef012c23Sbeck const uint8_t *staple, size_t staple_len) 391ef012c23Sbeck { 392ef012c23Sbeck struct tls_keypair *keypair; 393ef012c23Sbeck 394ef012c23Sbeck if ((keypair = tls_keypair_new()) == NULL) 395ef012c23Sbeck return (-1); 3962974e8f1Sjsing if (tls_keypair_set_cert_mem(keypair, &config->error, cert, cert_len) != 0) 397ef012c23Sbeck goto err; 39815339a8cSeric if (key != NULL && 39915339a8cSeric tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0) 400ef012c23Sbeck goto err; 401ef012c23Sbeck if (staple != NULL && 4022974e8f1Sjsing tls_keypair_set_ocsp_staple_mem(keypair, &config->error, staple, 4032974e8f1Sjsing staple_len) != 0) 404ef012c23Sbeck goto err; 40555272e79Sjsing 40655272e79Sjsing tls_config_keypair_add(config, keypair); 40755272e79Sjsing 40855272e79Sjsing return (0); 40955272e79Sjsing 41055272e79Sjsing err: 41155272e79Sjsing tls_keypair_free(keypair); 41255272e79Sjsing return (-1); 41355272e79Sjsing } 41455272e79Sjsing 41555272e79Sjsing int 41655272e79Sjsing tls_config_add_keypair_mem(struct tls_config *config, const uint8_t *cert, 41755272e79Sjsing size_t cert_len, const uint8_t *key, size_t key_len) 41855272e79Sjsing { 419ef012c23Sbeck return tls_config_add_keypair_mem_internal(config, cert, cert_len, key, 420ef012c23Sbeck key_len, NULL, 0); 421ef012c23Sbeck } 42255272e79Sjsing 423ef012c23Sbeck int 424ef012c23Sbeck tls_config_add_keypair_file(struct tls_config *config, 425ef012c23Sbeck const char *cert_file, const char *key_file) 426ef012c23Sbeck { 427ef012c23Sbeck return tls_config_add_keypair_file_internal(config, cert_file, 428ef012c23Sbeck key_file, NULL); 429ef012c23Sbeck } 43055272e79Sjsing 431ef012c23Sbeck int 432ef012c23Sbeck tls_config_add_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert, 433ef012c23Sbeck size_t cert_len, const uint8_t *key, size_t key_len, const uint8_t *staple, 434ef012c23Sbeck size_t staple_len) 435ef012c23Sbeck { 436ef012c23Sbeck return tls_config_add_keypair_mem_internal(config, cert, cert_len, key, 437ef012c23Sbeck key_len, staple, staple_len); 438ef012c23Sbeck } 43955272e79Sjsing 440ef012c23Sbeck int 441ef012c23Sbeck tls_config_add_keypair_ocsp_file(struct tls_config *config, 442ef012c23Sbeck const char *cert_file, const char *key_file, const char *ocsp_file) 443ef012c23Sbeck { 444ef012c23Sbeck return tls_config_add_keypair_file_internal(config, cert_file, 445ef012c23Sbeck key_file, ocsp_file); 44655272e79Sjsing } 44755272e79Sjsing 44855272e79Sjsing int 449b600beedSjsing tls_config_set_ca_file(struct tls_config *config, const char *ca_file) 450b600beedSjsing { 45103ce4948Sjsing return tls_config_load_file(&config->error, "CA", ca_file, 45203ce4948Sjsing &config->ca_mem, &config->ca_len); 453b600beedSjsing } 454b600beedSjsing 455b600beedSjsing int 456b600beedSjsing tls_config_set_ca_path(struct tls_config *config, const char *ca_path) 457b600beedSjsing { 458bb4cb1b0Sjsing return tls_set_string(&config->ca_path, ca_path); 459b600beedSjsing } 460b600beedSjsing 461b600beedSjsing int 46299cfb8c5Sreyk tls_config_set_ca_mem(struct tls_config *config, const uint8_t *ca, size_t len) 46399cfb8c5Sreyk { 464bb4cb1b0Sjsing return tls_set_mem(&config->ca_mem, &config->ca_len, ca, len); 46599cfb8c5Sreyk } 46699cfb8c5Sreyk 46799cfb8c5Sreyk int 468b600beedSjsing tls_config_set_cert_file(struct tls_config *config, const char *cert_file) 469b600beedSjsing { 47003ce4948Sjsing return tls_keypair_set_cert_file(config->keypair, &config->error, 47103ce4948Sjsing cert_file); 472b600beedSjsing } 473b600beedSjsing 474b600beedSjsing int 475b600beedSjsing tls_config_set_cert_mem(struct tls_config *config, const uint8_t *cert, 476b600beedSjsing size_t len) 477b600beedSjsing { 4782974e8f1Sjsing return tls_keypair_set_cert_mem(config->keypair, &config->error, 4792974e8f1Sjsing cert, len); 480b600beedSjsing } 481b600beedSjsing 482b600beedSjsing int 483b600beedSjsing tls_config_set_ciphers(struct tls_config *config, const char *ciphers) 484b600beedSjsing { 485c3bcced5Sjsing SSL_CTX *ssl_ctx = NULL; 486c3bcced5Sjsing 48785f64a89Sjsing if (ciphers == NULL || 48885f64a89Sjsing strcasecmp(ciphers, "default") == 0 || 48985f64a89Sjsing strcasecmp(ciphers, "secure") == 0) 49085f64a89Sjsing ciphers = TLS_CIPHERS_DEFAULT; 491c52398cfSjsing else if (strcasecmp(ciphers, "compat") == 0) 49285f64a89Sjsing ciphers = TLS_CIPHERS_COMPAT; 493c52398cfSjsing else if (strcasecmp(ciphers, "legacy") == 0) 494c52398cfSjsing ciphers = TLS_CIPHERS_LEGACY; 495c52398cfSjsing else if (strcasecmp(ciphers, "all") == 0 || 496c52398cfSjsing strcasecmp(ciphers, "insecure") == 0) 497c52398cfSjsing ciphers = TLS_CIPHERS_ALL; 49885f64a89Sjsing 499c3bcced5Sjsing if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { 5007a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, 5017a756d37Sjoshua "out of memory"); 5027add217bSjsing goto err; 503c3bcced5Sjsing } 504c3bcced5Sjsing if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { 5057a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 5067a756d37Sjoshua "no ciphers for '%s'", ciphers); 5077add217bSjsing goto err; 508c3bcced5Sjsing } 509c3bcced5Sjsing 510c3bcced5Sjsing SSL_CTX_free(ssl_ctx); 511bb4cb1b0Sjsing return tls_set_string(&config->ciphers, ciphers); 512c3bcced5Sjsing 5137add217bSjsing err: 514c3bcced5Sjsing SSL_CTX_free(ssl_ctx); 515c3bcced5Sjsing return -1; 516b600beedSjsing } 517b600beedSjsing 518b600beedSjsing int 51980bc881dSjsing tls_config_set_crl_file(struct tls_config *config, const char *crl_file) 52080bc881dSjsing { 52180bc881dSjsing return tls_config_load_file(&config->error, "CRL", crl_file, 52280bc881dSjsing &config->crl_mem, &config->crl_len); 52380bc881dSjsing } 52480bc881dSjsing 52580bc881dSjsing int 52680bc881dSjsing tls_config_set_crl_mem(struct tls_config *config, const uint8_t *crl, 52780bc881dSjsing size_t len) 52880bc881dSjsing { 529bb4cb1b0Sjsing return tls_set_mem(&config->crl_mem, &config->crl_len, crl, len); 53080bc881dSjsing } 53180bc881dSjsing 53280bc881dSjsing int 5339e5deb48Sjsing tls_config_set_dheparams(struct tls_config *config, const char *params) 5349e5deb48Sjsing { 5359e5deb48Sjsing int keylen; 5369e5deb48Sjsing 5379e5deb48Sjsing if (params == NULL || strcasecmp(params, "none") == 0) 5389e5deb48Sjsing keylen = 0; 5399e5deb48Sjsing else if (strcasecmp(params, "auto") == 0) 5409e5deb48Sjsing keylen = -1; 5414ba51adaSjsing else if (strcasecmp(params, "legacy") == 0) 5429e5deb48Sjsing keylen = 1024; 543a88e9e95Sjsing else { 5447a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 5457a756d37Sjoshua "invalid dhe param '%s'", params); 5469e5deb48Sjsing return (-1); 547a88e9e95Sjsing } 5489e5deb48Sjsing 5499e5deb48Sjsing config->dheparams = keylen; 5509e5deb48Sjsing 5519e5deb48Sjsing return (0); 5529e5deb48Sjsing } 5539e5deb48Sjsing 5549e5deb48Sjsing int 5554896de1eSjsing tls_config_set_ecdhecurve(struct tls_config *config, const char *curve) 556b600beedSjsing { 5571556a9e0Sjsing if (curve == NULL || 5581556a9e0Sjsing strcasecmp(curve, "none") == 0 || 5591556a9e0Sjsing strcasecmp(curve, "auto") == 0) { 5601556a9e0Sjsing curve = TLS_ECDHE_CURVES; 5611556a9e0Sjsing } else if (strchr(curve, ',') != NULL || strchr(curve, ':') != NULL) { 5627a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 5637a756d37Sjoshua "invalid ecdhe curve '%s'", curve); 564b600beedSjsing return (-1); 565a88e9e95Sjsing } 566b600beedSjsing 5674896de1eSjsing return tls_config_set_ecdhecurves(config, curve); 5684896de1eSjsing } 5694896de1eSjsing 5704896de1eSjsing int 5714896de1eSjsing tls_config_set_ecdhecurves(struct tls_config *config, const char *curves) 5724896de1eSjsing { 5734896de1eSjsing int *curves_list = NULL, *curves_new; 5744896de1eSjsing size_t curves_num = 0; 5754896de1eSjsing char *cs = NULL; 5764896de1eSjsing char *p, *q; 5774896de1eSjsing int rv = -1; 5784896de1eSjsing int nid; 5794896de1eSjsing 5804896de1eSjsing free(config->ecdhecurves); 5814896de1eSjsing config->ecdhecurves = NULL; 5824896de1eSjsing config->ecdhecurves_len = 0; 5834896de1eSjsing 5844896de1eSjsing if (curves == NULL || strcasecmp(curves, "default") == 0) 5854896de1eSjsing curves = TLS_ECDHE_CURVES; 5864896de1eSjsing 5874896de1eSjsing if ((cs = strdup(curves)) == NULL) { 5887a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, 5897a756d37Sjoshua "out of memory"); 5904896de1eSjsing goto err; 5914896de1eSjsing } 5924896de1eSjsing 5934896de1eSjsing q = cs; 5944896de1eSjsing while ((p = strsep(&q, ",:")) != NULL) { 5954896de1eSjsing while (*p == ' ' || *p == '\t') 5964896de1eSjsing p++; 5974896de1eSjsing 5984896de1eSjsing nid = OBJ_sn2nid(p); 5994896de1eSjsing if (nid == NID_undef) 6004896de1eSjsing nid = OBJ_ln2nid(p); 6014896de1eSjsing if (nid == NID_undef) 6024896de1eSjsing nid = EC_curve_nist2nid(p); 6034896de1eSjsing if (nid == NID_undef) { 6047a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 6054896de1eSjsing "invalid ecdhe curve '%s'", p); 6064896de1eSjsing goto err; 6074896de1eSjsing } 6084896de1eSjsing 6094896de1eSjsing if ((curves_new = reallocarray(curves_list, curves_num + 1, 6104896de1eSjsing sizeof(int))) == NULL) { 6117a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_OUT_OF_MEMORY, 6127a756d37Sjoshua "out of memory"); 6134896de1eSjsing goto err; 6144896de1eSjsing } 6154896de1eSjsing curves_list = curves_new; 6164896de1eSjsing curves_list[curves_num] = nid; 6174896de1eSjsing curves_num++; 6184896de1eSjsing } 6194896de1eSjsing 6204896de1eSjsing config->ecdhecurves = curves_list; 6214896de1eSjsing config->ecdhecurves_len = curves_num; 6224896de1eSjsing curves_list = NULL; 6234896de1eSjsing 6244896de1eSjsing rv = 0; 6254896de1eSjsing 6264896de1eSjsing err: 6274896de1eSjsing free(cs); 6284896de1eSjsing free(curves_list); 6294896de1eSjsing 6304896de1eSjsing return (rv); 631b600beedSjsing } 632b600beedSjsing 633b600beedSjsing int 634b600beedSjsing tls_config_set_key_file(struct tls_config *config, const char *key_file) 635b600beedSjsing { 63603ce4948Sjsing return tls_keypair_set_key_file(config->keypair, &config->error, 63703ce4948Sjsing key_file); 638b600beedSjsing } 639b600beedSjsing 640b600beedSjsing int 641b600beedSjsing tls_config_set_key_mem(struct tls_config *config, const uint8_t *key, 642b600beedSjsing size_t len) 643b600beedSjsing { 6442974e8f1Sjsing return tls_keypair_set_key_mem(config->keypair, &config->error, 6452974e8f1Sjsing key, len); 6461fe9fea1Sjsing } 6471fe9fea1Sjsing 648ef012c23Sbeck static int 649ef012c23Sbeck tls_config_set_keypair_file_internal(struct tls_config *config, 650ef012c23Sbeck const char *cert_file, const char *key_file, const char *ocsp_file) 6511fe9fea1Sjsing { 6521fe9fea1Sjsing if (tls_config_set_cert_file(config, cert_file) != 0) 6531fe9fea1Sjsing return (-1); 6541fe9fea1Sjsing if (tls_config_set_key_file(config, key_file) != 0) 6551fe9fea1Sjsing return (-1); 656ef012c23Sbeck if (ocsp_file != NULL && 657ef012c23Sbeck tls_config_set_ocsp_staple_file(config, ocsp_file) != 0) 658ef012c23Sbeck return (-1); 6591fe9fea1Sjsing 6601fe9fea1Sjsing return (0); 6611fe9fea1Sjsing } 6621fe9fea1Sjsing 663ef012c23Sbeck static int 664ef012c23Sbeck tls_config_set_keypair_mem_internal(struct tls_config *config, const uint8_t *cert, 665ef012c23Sbeck size_t cert_len, const uint8_t *key, size_t key_len, 666ef012c23Sbeck const uint8_t *staple, size_t staple_len) 667ef012c23Sbeck { 668ef012c23Sbeck if (tls_config_set_cert_mem(config, cert, cert_len) != 0) 669ef012c23Sbeck return (-1); 670ef012c23Sbeck if (tls_config_set_key_mem(config, key, key_len) != 0) 671ef012c23Sbeck return (-1); 672ef012c23Sbeck if ((staple != NULL) && 673ef012c23Sbeck (tls_config_set_ocsp_staple_mem(config, staple, staple_len) != 0)) 674ef012c23Sbeck return (-1); 675ef012c23Sbeck 676ef012c23Sbeck return (0); 677ef012c23Sbeck } 678ef012c23Sbeck 679ef012c23Sbeck int 680ef012c23Sbeck tls_config_set_keypair_file(struct tls_config *config, 681ef012c23Sbeck const char *cert_file, const char *key_file) 682ef012c23Sbeck { 683ef012c23Sbeck return tls_config_set_keypair_file_internal(config, cert_file, key_file, 684ef012c23Sbeck NULL); 685ef012c23Sbeck } 686ef012c23Sbeck 6871fe9fea1Sjsing int 6881fe9fea1Sjsing tls_config_set_keypair_mem(struct tls_config *config, const uint8_t *cert, 6891fe9fea1Sjsing size_t cert_len, const uint8_t *key, size_t key_len) 6901fe9fea1Sjsing { 691ef012c23Sbeck return tls_config_set_keypair_mem_internal(config, cert, cert_len, 692ef012c23Sbeck key, key_len, NULL, 0); 693b600beedSjsing } 694b600beedSjsing 6952b50121aSjsing int 696ef012c23Sbeck tls_config_set_keypair_ocsp_file(struct tls_config *config, 697ef012c23Sbeck const char *cert_file, const char *key_file, const char *ocsp_file) 698ef012c23Sbeck { 699ef012c23Sbeck return tls_config_set_keypair_file_internal(config, cert_file, key_file, 700ef012c23Sbeck ocsp_file); 701ef012c23Sbeck } 702ef012c23Sbeck 703ef012c23Sbeck int 704ef012c23Sbeck tls_config_set_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert, 705ef012c23Sbeck size_t cert_len, const uint8_t *key, size_t key_len, 706ef012c23Sbeck const uint8_t *staple, size_t staple_len) 707ef012c23Sbeck { 708ef012c23Sbeck return tls_config_set_keypair_mem_internal(config, cert, cert_len, 709ef012c23Sbeck key, key_len, staple, staple_len); 710ef012c23Sbeck } 711ef012c23Sbeck 712ef012c23Sbeck 713ef012c23Sbeck int 714b600beedSjsing tls_config_set_protocols(struct tls_config *config, uint32_t protocols) 715b600beedSjsing { 716b600beedSjsing config->protocols = protocols; 7172b50121aSjsing 7182b50121aSjsing return (0); 719b600beedSjsing } 720b600beedSjsing 7212b50121aSjsing int 7220dd084b9Sjsing tls_config_set_session_fd(struct tls_config *config, int session_fd) 7230dd084b9Sjsing { 7240dd084b9Sjsing struct stat sb; 7250dd084b9Sjsing mode_t mugo; 7260dd084b9Sjsing 7270dd084b9Sjsing if (session_fd == -1) { 7280dd084b9Sjsing config->session_fd = session_fd; 7290dd084b9Sjsing return (0); 7300dd084b9Sjsing } 7310dd084b9Sjsing 7320dd084b9Sjsing if (fstat(session_fd, &sb) == -1) { 7337a756d37Sjoshua tls_config_set_error(config, TLS_ERROR_UNKNOWN, 7347a756d37Sjoshua "failed to stat session file"); 7350dd084b9Sjsing return (-1); 7360dd084b9Sjsing } 7370dd084b9Sjsing if (!S_ISREG(sb.st_mode)) { 7387a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 7390dd084b9Sjsing "session file is not a regular file"); 7400dd084b9Sjsing return (-1); 7410dd084b9Sjsing } 7420dd084b9Sjsing 7430dd084b9Sjsing if (sb.st_uid != getuid()) { 7447a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 7457a756d37Sjoshua "session file has incorrect owner (uid %u != %u)", 7467a756d37Sjoshua sb.st_uid, getuid()); 7470dd084b9Sjsing return (-1); 7480dd084b9Sjsing } 7490dd084b9Sjsing mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO); 7500dd084b9Sjsing if (mugo != (S_IRUSR|S_IWUSR)) { 7517a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 7527a756d37Sjoshua "session file has incorrect permissions (%o != 600)", mugo); 7530dd084b9Sjsing return (-1); 7540dd084b9Sjsing } 7550dd084b9Sjsing 7560dd084b9Sjsing config->session_fd = session_fd; 7570dd084b9Sjsing 7580dd084b9Sjsing return (0); 7590dd084b9Sjsing } 7600dd084b9Sjsing 7610dd084b9Sjsing int 7629ecbddc1Seric tls_config_set_sign_cb(struct tls_config *config, tls_sign_cb cb, void *cb_arg) 7639ecbddc1Seric { 7649ecbddc1Seric config->use_fake_private_key = 1; 7659ecbddc1Seric config->skip_private_key_check = 1; 7669ecbddc1Seric config->sign_cb = cb; 7679ecbddc1Seric config->sign_cb_arg = cb_arg; 7689ecbddc1Seric 7699ecbddc1Seric return (0); 7709ecbddc1Seric } 7719ecbddc1Seric 7729ecbddc1Seric int 773b600beedSjsing tls_config_set_verify_depth(struct tls_config *config, int verify_depth) 774b600beedSjsing { 775b600beedSjsing config->verify_depth = verify_depth; 7762b50121aSjsing 7772b50121aSjsing return (0); 778b600beedSjsing } 779b600beedSjsing 780b600beedSjsing void 781c57e6ec0Sjsing tls_config_prefer_ciphers_client(struct tls_config *config) 782c57e6ec0Sjsing { 783c57e6ec0Sjsing config->ciphers_server = 0; 784c57e6ec0Sjsing } 785c57e6ec0Sjsing 786c57e6ec0Sjsing void 787c57e6ec0Sjsing tls_config_prefer_ciphers_server(struct tls_config *config) 788c57e6ec0Sjsing { 789c57e6ec0Sjsing config->ciphers_server = 1; 790c57e6ec0Sjsing } 791c57e6ec0Sjsing 792c57e6ec0Sjsing void 793b600beedSjsing tls_config_insecure_noverifycert(struct tls_config *config) 794b600beedSjsing { 795b600beedSjsing config->verify_cert = 0; 796b600beedSjsing } 797b600beedSjsing 798b600beedSjsing void 7991ff22c4bSjsing tls_config_insecure_noverifyname(struct tls_config *config) 8001ff22c4bSjsing { 8011ff22c4bSjsing config->verify_name = 0; 8021ff22c4bSjsing } 8031ff22c4bSjsing 8041ff22c4bSjsing void 805615956a0Sjsing tls_config_insecure_noverifytime(struct tls_config *config) 806615956a0Sjsing { 807615956a0Sjsing config->verify_time = 0; 808615956a0Sjsing } 809615956a0Sjsing 810615956a0Sjsing void 811b600beedSjsing tls_config_verify(struct tls_config *config) 812b600beedSjsing { 813b600beedSjsing config->verify_cert = 1; 8140ca7b9dfSjsing config->verify_name = 1; 815615956a0Sjsing config->verify_time = 1; 816b600beedSjsing } 81751f3bd3dSbeck 81851f3bd3dSbeck void 81969013f12Sbeck tls_config_ocsp_require_stapling(struct tls_config *config) 82069013f12Sbeck { 82169013f12Sbeck config->ocsp_require_stapling = 1; 82269013f12Sbeck } 82369013f12Sbeck 82469013f12Sbeck void 82551f3bd3dSbeck tls_config_verify_client(struct tls_config *config) 82651f3bd3dSbeck { 82751f3bd3dSbeck config->verify_client = 1; 82851f3bd3dSbeck } 82951f3bd3dSbeck 83051f3bd3dSbeck void 83151f3bd3dSbeck tls_config_verify_client_optional(struct tls_config *config) 83251f3bd3dSbeck { 83351f3bd3dSbeck config->verify_client = 2; 83451f3bd3dSbeck } 835668bec95Sbeck 836c793ca29Sbeck void 837c793ca29Sbeck tls_config_skip_private_key_check(struct tls_config *config) 838c793ca29Sbeck { 839c793ca29Sbeck config->skip_private_key_check = 1; 840c793ca29Sbeck } 841c793ca29Sbeck 84215339a8cSeric void 84315339a8cSeric tls_config_use_fake_private_key(struct tls_config *config) 84415339a8cSeric { 84515339a8cSeric config->use_fake_private_key = 1; 846e7e46248Seric config->skip_private_key_check = 1; 84715339a8cSeric } 84815339a8cSeric 849668bec95Sbeck int 850668bec95Sbeck tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file) 851668bec95Sbeck { 8529d519145Sbeck return tls_keypair_set_ocsp_staple_file(config->keypair, &config->error, 8539d519145Sbeck staple_file); 854668bec95Sbeck } 855668bec95Sbeck 856668bec95Sbeck int 857ef012c23Sbeck tls_config_set_ocsp_staple_mem(struct tls_config *config, const uint8_t *staple, 858ef012c23Sbeck size_t len) 859668bec95Sbeck { 8602974e8f1Sjsing return tls_keypair_set_ocsp_staple_mem(config->keypair, &config->error, 8612974e8f1Sjsing staple, len); 862668bec95Sbeck } 86347c43cfeSclaudio 86447c43cfeSclaudio int 86547c43cfeSclaudio tls_config_set_session_id(struct tls_config *config, 86647c43cfeSclaudio const unsigned char *session_id, size_t len) 86747c43cfeSclaudio { 86847c43cfeSclaudio if (len > TLS_MAX_SESSION_ID_LENGTH) { 8692d60058eSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 8707a756d37Sjoshua "session ID too large"); 87147c43cfeSclaudio return (-1); 87247c43cfeSclaudio } 87347c43cfeSclaudio memset(config->session_id, 0, sizeof(config->session_id)); 87447c43cfeSclaudio memcpy(config->session_id, session_id, len); 87547c43cfeSclaudio return (0); 87647c43cfeSclaudio } 87747c43cfeSclaudio 87847c43cfeSclaudio int 87947c43cfeSclaudio tls_config_set_session_lifetime(struct tls_config *config, int lifetime) 88047c43cfeSclaudio { 88147c43cfeSclaudio if (lifetime > TLS_MAX_SESSION_TIMEOUT) { 8822d60058eSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 8837a756d37Sjoshua "session lifetime too large"); 88447c43cfeSclaudio return (-1); 88547c43cfeSclaudio } 88647c43cfeSclaudio if (lifetime != 0 && lifetime < TLS_MIN_SESSION_TIMEOUT) { 8872d60058eSjoshua tls_config_set_errorx(config, TLS_ERROR_INVALID_ARGUMENT, 8887a756d37Sjoshua "session lifetime too small"); 88947c43cfeSclaudio return (-1); 89047c43cfeSclaudio } 89147c43cfeSclaudio 89247c43cfeSclaudio config->session_lifetime = lifetime; 89347c43cfeSclaudio return (0); 89447c43cfeSclaudio } 89547c43cfeSclaudio 89647c43cfeSclaudio int 89747c43cfeSclaudio tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev, 89847c43cfeSclaudio unsigned char *key, size_t keylen) 89947c43cfeSclaudio { 90047c43cfeSclaudio struct tls_ticket_key newkey; 90147c43cfeSclaudio int i; 90247c43cfeSclaudio 90347c43cfeSclaudio if (TLS_TICKET_KEY_SIZE != keylen || 90447c43cfeSclaudio sizeof(newkey.aes_key) + sizeof(newkey.hmac_key) > keylen) { 9057a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 90647c43cfeSclaudio "wrong amount of ticket key data"); 90747c43cfeSclaudio return (-1); 90847c43cfeSclaudio } 90947c43cfeSclaudio 91047c43cfeSclaudio keyrev = htonl(keyrev); 91147c43cfeSclaudio memset(&newkey, 0, sizeof(newkey)); 91247c43cfeSclaudio memcpy(newkey.key_name, &keyrev, sizeof(keyrev)); 91347c43cfeSclaudio memcpy(newkey.aes_key, key, sizeof(newkey.aes_key)); 91447c43cfeSclaudio memcpy(newkey.hmac_key, key + sizeof(newkey.aes_key), 91547c43cfeSclaudio sizeof(newkey.hmac_key)); 91647c43cfeSclaudio newkey.time = time(NULL); 91747c43cfeSclaudio 91847c43cfeSclaudio for (i = 0; i < TLS_NUM_TICKETS; i++) { 91947c43cfeSclaudio struct tls_ticket_key *tk = &config->ticket_keys[i]; 92047c43cfeSclaudio if (memcmp(newkey.key_name, tk->key_name, 92147c43cfeSclaudio sizeof(tk->key_name)) != 0) 92247c43cfeSclaudio continue; 92347c43cfeSclaudio 92447c43cfeSclaudio /* allow re-entry of most recent key */ 92547c43cfeSclaudio if (i == 0 && memcmp(newkey.aes_key, tk->aes_key, 92647c43cfeSclaudio sizeof(tk->aes_key)) == 0 && memcmp(newkey.hmac_key, 92747c43cfeSclaudio tk->hmac_key, sizeof(tk->hmac_key)) == 0) 92847c43cfeSclaudio return (0); 9297a756d37Sjoshua tls_config_set_errorx(config, TLS_ERROR_UNKNOWN, 9307a756d37Sjoshua "ticket key already present"); 93147c43cfeSclaudio return (-1); 93247c43cfeSclaudio } 93347c43cfeSclaudio 93447c43cfeSclaudio memmove(&config->ticket_keys[1], &config->ticket_keys[0], 93547c43cfeSclaudio sizeof(config->ticket_keys) - sizeof(config->ticket_keys[0])); 93647c43cfeSclaudio config->ticket_keys[0] = newkey; 93747c43cfeSclaudio 93847c43cfeSclaudio config->ticket_autorekey = 0; 93947c43cfeSclaudio 94047c43cfeSclaudio return (0); 94147c43cfeSclaudio } 94247c43cfeSclaudio 94347c43cfeSclaudio int 94447c43cfeSclaudio tls_config_ticket_autorekey(struct tls_config *config) 94547c43cfeSclaudio { 94647c43cfeSclaudio unsigned char key[TLS_TICKET_KEY_SIZE]; 94747c43cfeSclaudio int rv; 94847c43cfeSclaudio 94947c43cfeSclaudio arc4random_buf(key, sizeof(key)); 95047c43cfeSclaudio rv = tls_config_add_ticket_key(config, config->ticket_keyrev++, key, 95147c43cfeSclaudio sizeof(key)); 95247c43cfeSclaudio config->ticket_autorekey = 1; 95347c43cfeSclaudio return (rv); 95447c43cfeSclaudio } 955