diff options
author | claudio <> | 2017-01-24 01:48:05 +0000 |
---|---|---|
committer | claudio <> | 2017-01-24 01:48:05 +0000 |
commit | d78c389be49cfb5c1e450de1ffe9b19331871124 (patch) | |
tree | df70a1321916b965fd5fe88a72940612ae3642f4 /src/lib | |
parent | 2367558cf5d952b4f895457cfb15046d05a01529 (diff) | |
download | openbsd-d78c389be49cfb5c1e450de1ffe9b19331871124.tar.gz openbsd-d78c389be49cfb5c1e450de1ffe9b19331871124.tar.bz2 openbsd-d78c389be49cfb5c1e450de1ffe9b19331871124.zip |
Introduce ticket support. To enable them it is enough to set a positive
lifetime with tls_config_set_session_lifetime(). This enables tickets
and uses an internal automatic rekeying mode for the ticket keys.
If multiple processes are involved the following functions can be used to make
tickets work accross all instances:
- tls_config_set_session_id() sets the session identifier
- tls_config_add_ticket_key() adds an encryption and authentication key
For now only the last 4 keys added will be used (unless they are too old).
If tls_config_add_ticket_key() is used the caller must ensure to add new keys
regularly. It is best to do this 4 times per session lifetime (which is also
the ticket key lifetime).
Since tickets break PFS it is best to minimize the session lifetime according
to needs.
With a lot of help, input and OK beck@, jsing@
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libtls/Symbols.list | 3 | ||||
-rw-r--r-- | src/lib/libtls/tls.h | 11 | ||||
-rw-r--r-- | src/lib/libtls/tls_config.c | 102 | ||||
-rw-r--r-- | src/lib/libtls/tls_init.3 | 29 | ||||
-rw-r--r-- | src/lib/libtls/tls_internal.h | 24 | ||||
-rw-r--r-- | src/lib/libtls/tls_server.c | 96 |
6 files changed, 251 insertions, 14 deletions
diff --git a/src/lib/libtls/Symbols.list b/src/lib/libtls/Symbols.list index 7ed1d58bdc..a033e3e242 100644 --- a/src/lib/libtls/Symbols.list +++ b/src/lib/libtls/Symbols.list | |||
@@ -5,6 +5,7 @@ tls_client | |||
5 | tls_close | 5 | tls_close |
6 | tls_config_add_keypair_file | 6 | tls_config_add_keypair_file |
7 | tls_config_add_keypair_mem | 7 | tls_config_add_keypair_mem |
8 | tls_config_add_ticket_key | ||
8 | tls_config_clear_keys | 9 | tls_config_clear_keys |
9 | tls_config_error | 10 | tls_config_error |
10 | tls_config_free | 11 | tls_config_free |
@@ -32,6 +33,8 @@ tls_config_set_keypair_mem | |||
32 | tls_config_set_ocsp_staple_mem | 33 | tls_config_set_ocsp_staple_mem |
33 | tls_config_set_ocsp_staple_file | 34 | tls_config_set_ocsp_staple_file |
34 | tls_config_set_protocols | 35 | tls_config_set_protocols |
36 | tls_config_set_session_id | ||
37 | tls_config_set_session_lifetime | ||
35 | tls_config_set_verify_depth | 38 | tls_config_set_verify_depth |
36 | tls_config_verify | 39 | tls_config_verify |
37 | tls_config_verify_client | 40 | tls_config_verify_client |
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h index 645204a170..25d7c258e7 100644 --- a/src/lib/libtls/tls.h +++ b/src/lib/libtls/tls.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls.h,v 1.44 2017/01/22 03:59:30 jsing Exp $ */ | 1 | /* $OpenBSD: tls.h,v 1.45 2017/01/24 01:48:05 claudio Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -66,6 +66,9 @@ extern "C" { | |||
66 | #define TLS_CRL_REASON_PRIVILEGE_WITHDRAWN 9 | 66 | #define TLS_CRL_REASON_PRIVILEGE_WITHDRAWN 9 |
67 | #define TLS_CRL_REASON_AA_COMPROMISE 10 | 67 | #define TLS_CRL_REASON_AA_COMPROMISE 10 |
68 | 68 | ||
69 | #define TLS_MAX_SESSION_ID_LENGTH 32 | ||
70 | #define TLS_TICKET_KEY_SIZE 48 | ||
71 | |||
69 | struct tls; | 72 | struct tls; |
70 | struct tls_config; | 73 | struct tls_config; |
71 | 74 | ||
@@ -128,6 +131,12 @@ void tls_config_verify_client_optional(struct tls_config *_config); | |||
128 | void tls_config_clear_keys(struct tls_config *_config); | 131 | void tls_config_clear_keys(struct tls_config *_config); |
129 | int tls_config_parse_protocols(uint32_t *_protocols, const char *_protostr); | 132 | int tls_config_parse_protocols(uint32_t *_protocols, const char *_protostr); |
130 | 133 | ||
134 | int tls_config_set_session_id(struct tls_config *_config, | ||
135 | const unsigned char *_session_id, size_t _len); | ||
136 | int tls_config_set_session_lifetime(struct tls_config *_config, int _lifetime); | ||
137 | int tls_config_add_ticket_key(struct tls_config *_config, uint32_t _keyrev, | ||
138 | unsigned char *_key, size_t _keylen); | ||
139 | |||
131 | struct tls *tls_client(void); | 140 | struct tls *tls_client(void); |
132 | struct tls *tls_server(void); | 141 | struct tls *tls_server(void); |
133 | int tls_configure(struct tls *_ctx, struct tls_config *_config); | 142 | int tls_configure(struct tls *_ctx, struct tls_config *_config); |
diff --git a/src/lib/libtls/tls_config.c b/src/lib/libtls/tls_config.c index 5bc671fc99..8fa810461c 100644 --- a/src/lib/libtls/tls_config.c +++ b/src/lib/libtls/tls_config.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls_config.c,v 1.33 2016/11/11 14:02:24 jsing Exp $ */ | 1 | /* $OpenBSD: tls_config.c,v 1.34 2017/01/24 01:48:05 claudio Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -177,6 +177,7 @@ struct tls_config * | |||
177 | tls_config_new(void) | 177 | tls_config_new(void) |
178 | { | 178 | { |
179 | struct tls_config *config; | 179 | struct tls_config *config; |
180 | unsigned char sid[TLS_MAX_SESSION_ID_LENGTH]; | ||
180 | 181 | ||
181 | if ((config = calloc(1, sizeof(*config))) == NULL) | 182 | if ((config = calloc(1, sizeof(*config))) == NULL) |
182 | return (NULL); | 183 | return (NULL); |
@@ -199,6 +200,17 @@ tls_config_new(void) | |||
199 | if (tls_config_set_verify_depth(config, 6) != 0) | 200 | if (tls_config_set_verify_depth(config, 6) != 0) |
200 | goto err; | 201 | goto err; |
201 | 202 | ||
203 | /* | ||
204 | * Set session ID context to a random value. For the simple case | ||
205 | * of a single process server this is good enough. For multiprocess | ||
206 | * servers the session ID needs to be set by the caller. | ||
207 | */ | ||
208 | arc4random_buf(sid, sizeof(sid)); | ||
209 | if (tls_config_set_session_id(config, sid, sizeof(sid)) != 0) | ||
210 | goto err; | ||
211 | config->ticket_keyrev = arc4random(); | ||
212 | config->ticket_autorekey = 1; | ||
213 | |||
202 | tls_config_prefer_ciphers_server(config); | 214 | tls_config_prefer_ciphers_server(config); |
203 | 215 | ||
204 | tls_config_verify(config); | 216 | tls_config_verify(config); |
@@ -661,3 +673,91 @@ tls_config_set_ocsp_staple_mem(struct tls_config *config, char *staple, size_t l | |||
661 | { | 673 | { |
662 | return set_mem(&config->ocsp_staple, &config->ocsp_staple_len, staple, len); | 674 | return set_mem(&config->ocsp_staple, &config->ocsp_staple_len, staple, len); |
663 | } | 675 | } |
676 | |||
677 | int | ||
678 | tls_config_set_session_id(struct tls_config *config, | ||
679 | const unsigned char *session_id, size_t len) | ||
680 | { | ||
681 | if (len > TLS_MAX_SESSION_ID_LENGTH) { | ||
682 | tls_config_set_errorx(config, "session ID too large"); | ||
683 | return (-1); | ||
684 | } | ||
685 | memset(config->session_id, 0, sizeof(config->session_id)); | ||
686 | memcpy(config->session_id, session_id, len); | ||
687 | return (0); | ||
688 | } | ||
689 | |||
690 | int | ||
691 | tls_config_set_session_lifetime(struct tls_config *config, int lifetime) | ||
692 | { | ||
693 | if (lifetime > TLS_MAX_SESSION_TIMEOUT) { | ||
694 | tls_config_set_errorx(config, "session lifetime too large"); | ||
695 | return (-1); | ||
696 | } | ||
697 | if (lifetime != 0 && lifetime < TLS_MIN_SESSION_TIMEOUT) { | ||
698 | tls_config_set_errorx(config, "session lifetime too small"); | ||
699 | return (-1); | ||
700 | } | ||
701 | |||
702 | config->session_lifetime = lifetime; | ||
703 | return (0); | ||
704 | } | ||
705 | |||
706 | int | ||
707 | tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev, | ||
708 | unsigned char *key, size_t keylen) | ||
709 | { | ||
710 | struct tls_ticket_key newkey; | ||
711 | int i; | ||
712 | |||
713 | if (TLS_TICKET_KEY_SIZE != keylen || | ||
714 | sizeof(newkey.aes_key) + sizeof(newkey.hmac_key) > keylen) { | ||
715 | tls_config_set_errorx(config, | ||
716 | "wrong amount of ticket key data"); | ||
717 | return (-1); | ||
718 | } | ||
719 | |||
720 | keyrev = htonl(keyrev); | ||
721 | memset(&newkey, 0, sizeof(newkey)); | ||
722 | memcpy(newkey.key_name, &keyrev, sizeof(keyrev)); | ||
723 | memcpy(newkey.aes_key, key, sizeof(newkey.aes_key)); | ||
724 | memcpy(newkey.hmac_key, key + sizeof(newkey.aes_key), | ||
725 | sizeof(newkey.hmac_key)); | ||
726 | newkey.time = time(NULL); | ||
727 | |||
728 | for (i = 0; i < TLS_NUM_TICKETS; i++) { | ||
729 | struct tls_ticket_key *tk = &config->ticket_keys[i]; | ||
730 | if (memcmp(newkey.key_name, tk->key_name, | ||
731 | sizeof(tk->key_name)) != 0) | ||
732 | continue; | ||
733 | |||
734 | /* allow re-entry of most recent key */ | ||
735 | if (i == 0 && memcmp(newkey.aes_key, tk->aes_key, | ||
736 | sizeof(tk->aes_key)) == 0 && memcmp(newkey.hmac_key, | ||
737 | tk->hmac_key, sizeof(tk->hmac_key)) == 0) | ||
738 | return (0); | ||
739 | tls_config_set_errorx(config, "ticket key already present"); | ||
740 | return (-1); | ||
741 | } | ||
742 | |||
743 | memmove(&config->ticket_keys[1], &config->ticket_keys[0], | ||
744 | sizeof(config->ticket_keys) - sizeof(config->ticket_keys[0])); | ||
745 | config->ticket_keys[0] = newkey; | ||
746 | |||
747 | config->ticket_autorekey = 0; | ||
748 | |||
749 | return (0); | ||
750 | } | ||
751 | |||
752 | int | ||
753 | tls_config_ticket_autorekey(struct tls_config *config) | ||
754 | { | ||
755 | unsigned char key[TLS_TICKET_KEY_SIZE]; | ||
756 | int rv; | ||
757 | |||
758 | arc4random_buf(key, sizeof(key)); | ||
759 | rv = tls_config_add_ticket_key(config, config->ticket_keyrev++, key, | ||
760 | sizeof(key)); | ||
761 | config->ticket_autorekey = 1; | ||
762 | return (rv); | ||
763 | } | ||
diff --git a/src/lib/libtls/tls_init.3 b/src/lib/libtls/tls_init.3 index 05474016f4..f5cada93a5 100644 --- a/src/lib/libtls/tls_init.3 +++ b/src/lib/libtls/tls_init.3 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: tls_init.3,v 1.84 2017/01/24 01:16:26 claudio Exp $ | 1 | .\" $OpenBSD: tls_init.3,v 1.85 2017/01/24 01:48:05 claudio Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> | 3 | .\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> |
4 | .\" | 4 | .\" |
@@ -26,6 +26,7 @@ | |||
26 | .Nm tls_config_parse_protocols , | 26 | .Nm tls_config_parse_protocols , |
27 | .Nm tls_config_add_keypair_file , | 27 | .Nm tls_config_add_keypair_file , |
28 | .Nm tls_config_add_keypair_mem , | 28 | .Nm tls_config_add_keypair_mem , |
29 | .Nm tls_config_add_ticket_key , | ||
29 | .Nm tls_config_set_alpn , | 30 | .Nm tls_config_set_alpn , |
30 | .Nm tls_config_set_ca_file , | 31 | .Nm tls_config_set_ca_file , |
31 | .Nm tls_config_set_ca_path , | 32 | .Nm tls_config_set_ca_path , |
@@ -42,6 +43,8 @@ | |||
42 | .Nm tls_config_set_ocsp_staple_mem , | 43 | .Nm tls_config_set_ocsp_staple_mem , |
43 | .Nm tls_config_set_ocsp_staple_file , | 44 | .Nm tls_config_set_ocsp_staple_file , |
44 | .Nm tls_config_set_protocols , | 45 | .Nm tls_config_set_protocols , |
46 | .Nm tls_config_set_session_id , | ||
47 | .Nm tls_config_set_session_lifetime , | ||
45 | .Nm tls_config_set_verify_depth , | 48 | .Nm tls_config_set_verify_depth , |
46 | .Nm tls_config_prefer_ciphers_client , | 49 | .Nm tls_config_prefer_ciphers_client , |
47 | .Nm tls_config_prefer_ciphers_server , | 50 | .Nm tls_config_prefer_ciphers_server , |
@@ -111,6 +114,8 @@ | |||
111 | .Ft "int" | 114 | .Ft "int" |
112 | .Fn 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" | 115 | .Fn 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" |
113 | .Ft "int" | 116 | .Ft "int" |
117 | .Fn tls_config_add_ticket_key "struct tls_config *config" "uint32_t keyrev" "unsigned char *key" "size_t keylen" | ||
118 | .Ft "int" | ||
114 | .Fn tls_config_set_alpn "struct tls_config *config" "const char *alpn" | 119 | .Fn tls_config_set_alpn "struct tls_config *config" "const char *alpn" |
115 | .Ft "int" | 120 | .Ft "int" |
116 | .Fn tls_config_set_ca_file "struct tls_config *config" "const char *ca_file" | 121 | .Fn tls_config_set_ca_file "struct tls_config *config" "const char *ca_file" |
@@ -143,6 +148,10 @@ | |||
143 | .Ft "int" | 148 | .Ft "int" |
144 | .Fn tls_config_set_protocols "struct tls_config *config" "uint32_t protocols" | 149 | .Fn tls_config_set_protocols "struct tls_config *config" "uint32_t protocols" |
145 | .Ft "int" | 150 | .Ft "int" |
151 | .Fn tls_config_set_session_id "struct tls_config *config" "const unsigned char *session_id" "size_t len" | ||
152 | .Ft "int" | ||
153 | .Fn tls_config_set_session_lifetime "struct tls_config *config" "int lifetime" | ||
154 | .Ft "int" | ||
146 | .Fn tls_config_set_verify_depth "struct tls_config *config" "int verify_depth" | 155 | .Fn tls_config_set_verify_depth "struct tls_config *config" "int verify_depth" |
147 | .Ft "void" | 156 | .Ft "void" |
148 | .Fn tls_config_prefer_ciphers_client "struct tls_config *config" | 157 | .Fn tls_config_prefer_ciphers_client "struct tls_config *config" |
@@ -371,6 +380,14 @@ used as an alternative certificate for Server Name Indication (server only). | |||
371 | adds an additional public certificate and private key from memory, | 380 | adds an additional public certificate and private key from memory, |
372 | used as an alternative certificate for Server Name Indication (server only). | 381 | used as an alternative certificate for Server Name Indication (server only). |
373 | .It | 382 | .It |
383 | .Fn tls_config_add_ticket_key | ||
384 | adds a key used for the encryption and authentication of TLS tickets. | ||
385 | By default keys are generated and rotated automatically based on their lifetime. | ||
386 | This function should only be used to synchronise ticket encryption key accross | ||
387 | multiple processes. | ||
388 | Re-adding a known key will result in an error, unless it is the most recently | ||
389 | added key. | ||
390 | .It | ||
374 | .Fn tls_config_set_alpn | 391 | .Fn tls_config_set_alpn |
375 | sets the ALPN protocols that are supported. | 392 | sets the ALPN protocols that are supported. |
376 | The alpn string is a comma separated list of protocols, in order of preference. | 393 | The alpn string is a comma separated list of protocols, in order of preference. |
@@ -447,6 +464,16 @@ Additionally, the values | |||
447 | .Dv TLS_PROTOCOLS_DEFAULT | 464 | .Dv TLS_PROTOCOLS_DEFAULT |
448 | (TLSv1.2 only) may be used. | 465 | (TLSv1.2 only) may be used. |
449 | .It | 466 | .It |
467 | .Fn tls_config_set_session_id | ||
468 | sets the session identifier that will be used by the TLS server when | ||
469 | sessions are enabled. | ||
470 | By default a random value is used. | ||
471 | .It | ||
472 | .Fn tls_config_set_session_lifetime | ||
473 | sets the lifetime to be used for TLS sessions. | ||
474 | Session support is disabled if a lifetime of zero is specified, which is the | ||
475 | default. | ||
476 | .It | ||
450 | .Fn tls_config_set_verify_depth | 477 | .Fn tls_config_set_verify_depth |
451 | limits the number of intermediate certificates that will be followed during | 478 | limits the number of intermediate certificates that will be followed during |
452 | certificate validation. | 479 | certificate validation. |
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h index 1db186a05f..3650ca9462 100644 --- a/src/lib/libtls/tls_internal.h +++ b/src/lib/libtls/tls_internal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls_internal.h,v 1.50 2016/11/05 15:13:26 beck Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.51 2017/01/24 01:48:05 claudio Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> | 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> |
4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
@@ -53,6 +53,22 @@ struct tls_keypair { | |||
53 | size_t key_len; | 53 | size_t key_len; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | #define TLS_MIN_SESSION_TIMEOUT (4) | ||
57 | #define TLS_MAX_SESSION_TIMEOUT (24 * 60 * 60) | ||
58 | |||
59 | #define TLS_NUM_TICKETS 4 | ||
60 | #define TLS_TICKET_NAME_SIZE 16 | ||
61 | #define TLS_TICKET_AES_SIZE 32 | ||
62 | #define TLS_TICKET_HMAC_SIZE 16 | ||
63 | |||
64 | struct tls_ticket_key { | ||
65 | /* The key_name must be 16 bytes according to -lssl */ | ||
66 | unsigned char key_name[TLS_TICKET_NAME_SIZE]; | ||
67 | unsigned char aes_key[TLS_TICKET_AES_SIZE]; | ||
68 | unsigned char hmac_key[TLS_TICKET_HMAC_SIZE]; | ||
69 | time_t time; | ||
70 | }; | ||
71 | |||
56 | struct tls_config { | 72 | struct tls_config { |
57 | struct tls_error error; | 73 | struct tls_error error; |
58 | 74 | ||
@@ -70,6 +86,11 @@ struct tls_config { | |||
70 | char *ocsp_staple; | 86 | char *ocsp_staple; |
71 | size_t ocsp_staple_len; | 87 | size_t ocsp_staple_len; |
72 | uint32_t protocols; | 88 | uint32_t protocols; |
89 | unsigned char session_id[TLS_MAX_SESSION_ID_LENGTH]; | ||
90 | int session_lifetime; | ||
91 | struct tls_ticket_key ticket_keys[TLS_NUM_TICKETS]; | ||
92 | uint32_t ticket_keyrev; | ||
93 | int ticket_autorekey; | ||
73 | int verify_cert; | 94 | int verify_cert; |
74 | int verify_client; | 95 | int verify_client; |
75 | int verify_depth; | 96 | int verify_depth; |
@@ -171,6 +192,7 @@ int tls_handshake_server(struct tls *ctx); | |||
171 | 192 | ||
172 | int tls_config_load_file(struct tls_error *error, const char *filetype, | 193 | int tls_config_load_file(struct tls_error *error, const char *filetype, |
173 | const char *filename, char **buf, size_t *len); | 194 | const char *filename, char **buf, size_t *len); |
195 | int tls_config_ticket_autorekey(struct tls_config *config); | ||
174 | int tls_host_port(const char *hostport, char **host, char **port); | 196 | int tls_host_port(const char *hostport, char **host, char **port); |
175 | 197 | ||
176 | int tls_set_cbs(struct tls *ctx, | 198 | int tls_set_cbs(struct tls *ctx, |
diff --git a/src/lib/libtls/tls_server.c b/src/lib/libtls/tls_server.c index 091dd7a153..5bf87552cb 100644 --- a/src/lib/libtls/tls_server.c +++ b/src/lib/libtls/tls_server.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tls_server.c,v 1.32 2017/01/12 16:15:58 jsing Exp $ */ | 1 | /* $OpenBSD: tls_server.c,v 1.33 2017/01/24 01:48:05 claudio Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
4 | * | 4 | * |
@@ -116,6 +116,77 @@ tls_servername_cb(SSL *ssl, int *al, void *arg) | |||
116 | return (SSL_TLSEXT_ERR_ALERT_FATAL); | 116 | return (SSL_TLSEXT_ERR_ALERT_FATAL); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct tls_ticket_key * | ||
120 | tls_server_ticket_key(struct tls_config *config, unsigned char *keyname) | ||
121 | { | ||
122 | struct tls_ticket_key *key = NULL; | ||
123 | time_t now; | ||
124 | int i; | ||
125 | |||
126 | now = time(NULL); | ||
127 | if (config->ticket_autorekey == 1) { | ||
128 | if (now - 3 * (config->session_lifetime / 4) > | ||
129 | config->ticket_keys[0].time) { | ||
130 | if (tls_config_ticket_autorekey(config) == -1) | ||
131 | return (NULL); | ||
132 | } | ||
133 | } | ||
134 | for (i = 0; i < TLS_NUM_TICKETS; i++) { | ||
135 | struct tls_ticket_key *tk = &config->ticket_keys[i]; | ||
136 | if (now - config->session_lifetime > tk->time) | ||
137 | continue; | ||
138 | if (keyname == NULL || timingsafe_memcmp(keyname, | ||
139 | tk->key_name, sizeof(tk->key_name)) == 0) { | ||
140 | key = tk; | ||
141 | break; | ||
142 | } | ||
143 | } | ||
144 | return (key); | ||
145 | } | ||
146 | |||
147 | static int | ||
148 | tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, | ||
149 | EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode) | ||
150 | { | ||
151 | struct tls_ticket_key *key; | ||
152 | struct tls *tls_ctx; | ||
153 | |||
154 | if ((tls_ctx = SSL_get_app_data(ssl)) == NULL) | ||
155 | return (-1); | ||
156 | |||
157 | if (mode == 1) { | ||
158 | /* create new session */ | ||
159 | key = tls_server_ticket_key(tls_ctx->config, NULL); | ||
160 | if (key == NULL) { | ||
161 | tls_set_errorx(tls_ctx, "no valid ticket key found"); | ||
162 | return (-1); | ||
163 | } | ||
164 | |||
165 | memcpy(keyname, key->key_name, sizeof(key->key_name)); | ||
166 | arc4random_buf(iv, EVP_MAX_IV_LENGTH); | ||
167 | EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, | ||
168 | key->aes_key, iv); | ||
169 | HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), | ||
170 | EVP_sha256(), NULL); | ||
171 | return (0); | ||
172 | } else { | ||
173 | /* get key by name */ | ||
174 | key = tls_server_ticket_key(tls_ctx->config, keyname); | ||
175 | if (key == NULL) | ||
176 | return (0); | ||
177 | |||
178 | EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, | ||
179 | key->aes_key, iv); | ||
180 | HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), | ||
181 | EVP_sha256(), NULL); | ||
182 | |||
183 | /* time to renew the ticket? is it the primary key? */ | ||
184 | if (key != &tls_ctx->config->ticket_keys[0]) | ||
185 | return (2); | ||
186 | return (1); | ||
187 | } | ||
188 | } | ||
189 | |||
119 | static int | 190 | static int |
120 | tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, | 191 | tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, |
121 | X509 **cert) | 192 | X509 **cert) |
@@ -157,7 +228,6 @@ static int | |||
157 | tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, | 228 | tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, |
158 | struct tls_keypair *keypair) | 229 | struct tls_keypair *keypair) |
159 | { | 230 | { |
160 | unsigned char sid[SSL_MAX_SSL_SESSION_ID_LENGTH]; | ||
161 | EC_KEY *ecdh_key; | 231 | EC_KEY *ecdh_key; |
162 | 232 | ||
163 | SSL_CTX_free(*ssl_ctx); | 233 | SSL_CTX_free(*ssl_ctx); |
@@ -219,14 +289,20 @@ tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, | |||
219 | goto err; | 289 | goto err; |
220 | } | 290 | } |
221 | 291 | ||
222 | /* | 292 | if (ctx->config->session_lifetime > 0) { |
223 | * Set session ID context to a random value. We don't support | 293 | /* set the session lifetime and enable tickets */ |
224 | * persistent caching of sessions so it is OK to set a temporary | 294 | SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime); |
225 | * session ID context that is valid during run time. | 295 | SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET); |
226 | */ | 296 | if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx, |
227 | arc4random_buf(sid, sizeof(sid)); | 297 | tls_server_ticket_cb)) { |
228 | if (SSL_CTX_set_session_id_context(*ssl_ctx, sid, | 298 | tls_set_error(ctx, |
229 | sizeof(sid)) != 1) { | 299 | "failed to set the TLS ticket callback"); |
300 | goto err; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id, | ||
305 | sizeof(ctx->config->session_id)) != 1) { | ||
230 | tls_set_error(ctx, "failed to set session id context"); | 306 | tls_set_error(ctx, "failed to set session id context"); |
231 | goto err; | 307 | goto err; |
232 | } | 308 | } |