summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libtls/Symbols.list3
-rw-r--r--src/lib/libtls/tls.h11
-rw-r--r--src/lib/libtls/tls_config.c102
-rw-r--r--src/lib/libtls/tls_init.329
-rw-r--r--src/lib/libtls/tls_internal.h24
-rw-r--r--src/lib/libtls/tls_server.c96
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
5tls_close 5tls_close
6tls_config_add_keypair_file 6tls_config_add_keypair_file
7tls_config_add_keypair_mem 7tls_config_add_keypair_mem
8tls_config_add_ticket_key
8tls_config_clear_keys 9tls_config_clear_keys
9tls_config_error 10tls_config_error
10tls_config_free 11tls_config_free
@@ -32,6 +33,8 @@ tls_config_set_keypair_mem
32tls_config_set_ocsp_staple_mem 33tls_config_set_ocsp_staple_mem
33tls_config_set_ocsp_staple_file 34tls_config_set_ocsp_staple_file
34tls_config_set_protocols 35tls_config_set_protocols
36tls_config_set_session_id
37tls_config_set_session_lifetime
35tls_config_set_verify_depth 38tls_config_set_verify_depth
36tls_config_verify 39tls_config_verify
37tls_config_verify_client 40tls_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
69struct tls; 72struct tls;
70struct tls_config; 73struct tls_config;
71 74
@@ -128,6 +131,12 @@ void tls_config_verify_client_optional(struct tls_config *_config);
128void tls_config_clear_keys(struct tls_config *_config); 131void tls_config_clear_keys(struct tls_config *_config);
129int tls_config_parse_protocols(uint32_t *_protocols, const char *_protostr); 132int tls_config_parse_protocols(uint32_t *_protocols, const char *_protostr);
130 133
134int tls_config_set_session_id(struct tls_config *_config,
135 const unsigned char *_session_id, size_t _len);
136int tls_config_set_session_lifetime(struct tls_config *_config, int _lifetime);
137int tls_config_add_ticket_key(struct tls_config *_config, uint32_t _keyrev,
138 unsigned char *_key, size_t _keylen);
139
131struct tls *tls_client(void); 140struct tls *tls_client(void);
132struct tls *tls_server(void); 141struct tls *tls_server(void);
133int tls_configure(struct tls *_ctx, struct tls_config *_config); 142int 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 *
177tls_config_new(void) 177tls_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
677int
678tls_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
690int
691tls_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
706int
707tls_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
752int
753tls_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).
371adds an additional public certificate and private key from memory, 380adds an additional public certificate and private key from memory,
372used as an alternative certificate for Server Name Indication (server only). 381used as an alternative certificate for Server Name Indication (server only).
373.It 382.It
383.Fn tls_config_add_ticket_key
384adds a key used for the encryption and authentication of TLS tickets.
385By default keys are generated and rotated automatically based on their lifetime.
386This function should only be used to synchronise ticket encryption key accross
387multiple processes.
388Re-adding a known key will result in an error, unless it is the most recently
389added key.
390.It
374.Fn tls_config_set_alpn 391.Fn tls_config_set_alpn
375sets the ALPN protocols that are supported. 392sets the ALPN protocols that are supported.
376The alpn string is a comma separated list of protocols, in order of preference. 393The 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
468sets the session identifier that will be used by the TLS server when
469sessions are enabled.
470By default a random value is used.
471.It
472.Fn tls_config_set_session_lifetime
473sets the lifetime to be used for TLS sessions.
474Session support is disabled if a lifetime of zero is specified, which is the
475default.
476.It
450.Fn tls_config_set_verify_depth 477.Fn tls_config_set_verify_depth
451limits the number of intermediate certificates that will be followed during 478limits the number of intermediate certificates that will be followed during
452certificate validation. 479certificate 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
64struct 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
56struct tls_config { 72struct 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
172int tls_config_load_file(struct tls_error *error, const char *filetype, 193int 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);
195int tls_config_ticket_autorekey(struct tls_config *config);
174int tls_host_port(const char *hostport, char **host, char **port); 196int tls_host_port(const char *hostport, char **host, char **port);
175 197
176int tls_set_cbs(struct tls *ctx, 198int 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
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 }