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_config.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_config.c')
-rw-r--r-- | src/lib/libtls/tls_config.c | 102 |
1 files changed, 101 insertions, 1 deletions
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 | } | ||