summaryrefslogtreecommitdiff
path: root/src/lib/libtls/tls_server.c
diff options
context:
space:
mode:
authorclaudio <>2017-01-24 01:48:05 +0000
committerclaudio <>2017-01-24 01:48:05 +0000
commitd78c389be49cfb5c1e450de1ffe9b19331871124 (patch)
treedf70a1321916b965fd5fe88a72940612ae3642f4 /src/lib/libtls/tls_server.c
parent2367558cf5d952b4f895457cfb15046d05a01529 (diff)
downloadopenbsd-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.c96
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
119static struct tls_ticket_key *
120tls_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
147static int
148tls_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
119static int 190static int
120tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, 191tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error,
121 X509 **cert) 192 X509 **cert)
@@ -157,7 +228,6 @@ static int
157tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, 228tls_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 }