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/libtls/tls_server.c | |
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/libtls/tls_server.c')
-rw-r--r-- | src/lib/libtls/tls_server.c | 96 |
1 files changed, 86 insertions, 10 deletions
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 | } |