diff options
Diffstat (limited to 'lib/ext')
-rw-r--r-- | lib/ext/pre_shared_key.c | 209 | ||||
-rw-r--r-- | lib/ext/pre_shared_key.h | 1 | ||||
-rw-r--r-- | lib/ext/psk_ke_modes.c | 12 | ||||
-rw-r--r-- | lib/ext/session_ticket.c | 149 | ||||
-rw-r--r-- | lib/ext/session_ticket.h | 17 |
5 files changed, 249 insertions, 139 deletions
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c index b60e9d7cb2..27869eab7a 100644 --- a/lib/ext/pre_shared_key.c +++ b/lib/ext/pre_shared_key.c @@ -25,14 +25,47 @@ #include "secrets.h" #include "tls13/psk_ext_parser.h" #include "tls13/finished.h" +#include "tls13/session_ticket.h" #include "auth/psk_passwd.h" +#include <ext/session_ticket.h> #include <ext/pre_shared_key.h> +#include "tls13/psk_ext_parser.h" typedef struct { - uint16_t selected_identity; + struct tls13_nst_st *session_ticket; + uint8_t *rms; + size_t rms_size; } psk_ext_st; static int +compute_psk_from_ticket(const mac_entry_st *prf, + const uint8_t *rms, + gnutls_datum_t *nonce, gnutls_datum_t *key) +{ + int ret; + unsigned hash_size = prf->output_size; + char label[] = "resumption"; + + key->data = gnutls_malloc(hash_size); + key->size = hash_size; + if (key->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + ret = _tls13_expand_secret2(prf, + label, strlen(label), + nonce->data, nonce->size, + rms, + hash_size, + key->data); + if (ret < 0) { + _gnutls_free_datum(key); + return gnutls_assert_val(ret); + } + + return ret; +} + +static int compute_binder_key(const mac_entry_st *prf, const uint8_t *key, size_t keylen, void *out) @@ -181,27 +214,85 @@ client_send_params(gnutls_session_t session, gnutls_buffer_t extdata, const gnutls_psk_client_credentials_t cred) { - int ret, extdata_len = 0, ext_offset = 0; + int ret = 0, extdata_len = 0, ext_offset = 0; uint8_t binder_value[MAX_HASH_SIZE]; - size_t length, pos = extdata->length; - gnutls_datum_t username, key, client_hello; - const mac_entry_st *prf = _gnutls_mac_to_entry(cred->tls13_binder_algo); - unsigned hash_size = _gnutls_mac_get_algo_len(prf); + size_t length, pos; + const mac_entry_st *prf = NULL; + unsigned hash_size = 0; + struct tls13_nst_st ticket; + const uint8_t *rms = NULL; + time_t cur_time; + int ticket_age; + uint32_t ob_ticket_age = 0; + gnutls_datum_t username = { NULL, 0 }, key = { NULL, 0 }, + client_hello = { NULL, 0 }; + + memset(&ticket, 0, sizeof(struct tls13_nst_st)); + + if (cred) { + prf = _gnutls_mac_to_entry(cred->tls13_binder_algo); + hash_size = _gnutls_mac_get_algo_len(prf); + if (prf == NULL || hash_size == 0 || hash_size > 255) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = get_credentials(session, cred, &username, &key); + if (ret < 0) + return gnutls_assert_val(ret); + } - if (prf == NULL || hash_size == 0 || hash_size > 255) - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + /* No out-of-band PSKs - let's see if we have a session ticket to send */ + if (prf == NULL && session->internals.session_ticket_enable) { + ret = _gnutls13_session_ticket_get(session, &ticket); + if (ret > 0) { + /* We found a session ticket */ + prf = _gnutls_mac_to_entry(session->key.proto.tls13.kdf_original); + hash_size = _gnutls_mac_get_algo_len(prf); + if (unlikely(prf == NULL || hash_size == 0)) { + _gnutls13_session_ticket_unset(session); + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto cleanup; + } - memset(&username, 0, sizeof(gnutls_datum_t)); + /* Check whether the ticket is stale */ + cur_time = time(NULL); + ticket_age = cur_time - ticket.ticket_timestamp; + if (ticket_age < 0 || ticket_age > cur_time) { + _gnutls13_session_ticket_unset(session); + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto cleanup; + } + if ((unsigned int) ticket_age > ticket.ticket_lifetime) { + _gnutls13_session_ticket_unset(session); + ret = 0; + goto cleanup; + } + + username.data = ticket.ticket.data; + username.size = ticket.ticket.size; + + rms = session->key.proto.tls13.ap_rms_original.data; + ret = compute_psk_from_ticket(prf, + rms, + &ticket.ticket_nonce, &key); + if (ret < 0) { + _gnutls13_session_ticket_unset(session); + gnutls_assert(); + goto cleanup; + } + + /* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */ + ob_ticket_age = (ticket_age * 1000 + ticket.ticket_age_add) % 4294967296; + } + } - ret = get_credentials(session, cred, &username, &key); - if (ret < 0) - return gnutls_assert_val(ret); /* No credentials - this extension is not applicable */ - if (ret == 0) { + if (prf == NULL) { ret = 0; goto cleanup; } + /* Make some room for the identities length (16 bits) */ + pos = extdata->length; ret = _gnutls_buffer_append_prefix(extdata, 16, 0); if (ret < 0) { gnutls_assert_val(ret); @@ -220,8 +311,8 @@ client_send_params(gnutls_session_t session, gnutls_assert_val(ret); goto cleanup; } - /* Now append the ticket age, which is always zero for out-of-band PSKs */ - if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) { + /* Obfuscated ticket age */ + if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) { gnutls_assert_val(ret); goto cleanup; } @@ -269,6 +360,7 @@ client_send_params(gnutls_session_t session, ret = extdata_len; cleanup: + _gnutls13_session_ticket_destroy(&ticket); _gnutls_free_datum(&username); return ret; } @@ -294,15 +386,23 @@ static int server_recv_params(gnutls_session_t session, const gnutls_psk_server_credentials_t pskcred) { int ret; - const mac_entry_st *prf; + const mac_entry_st *prf = NULL; gnutls_datum_t full_client_hello; uint8_t binder_value[MAX_HASH_SIZE]; int psk_index = -1; + gnutls_datum_t key = { NULL, 0 }; gnutls_datum_t binder_recvd = { NULL, 0 }; - gnutls_datum_t key; + gnutls_datum_t ticket_bytes = { NULL, 0 }; + gnutls_datum_t ticket_nonce = { NULL, 0 }; + int ticket_age; + struct tls13_ticket_data ticket_data; unsigned hash_size; psk_ext_parser_t psk_parser; struct psk_st psk; + enum { + PSK = 1, + TICKET + } psk_kind = 0; ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len); if (ret == 0) { @@ -313,28 +413,74 @@ static int server_recv_params(gnutls_session_t session, } if (_gnutls13_psk_ext_parser_next_psk(psk_parser, &psk) >= 0) { + ticket_bytes.data = psk.identity.data; + ticket_bytes.size = psk.identity.size; + + if (_gnutls13_unpack_session_ticket(session, &ticket_bytes, &ticket_data) > 0) { + psk_index = psk.selected_index; + prf = _gnutls_mac_to_entry(ticket_data.kdf_id); + if (!prf) { + _gnutls13_ticket_data_destroy(&ticket_data); + return gnutls_assert_val(GNUTLS_E_INVALID_SESSION); + } + + session->internals.tls13_session_ticket_renew = 0; + + /* Check whether ticket is stale or not */ + ticket_age = psk.ob_ticket_age - ticket_data.ticket_age_add; + if (ticket_age < 0) { + session->internals.tls13_session_ticket_renew = 1; + _gnutls13_ticket_data_destroy(&ticket_data); + return 0; + } + if ((unsigned int) (ticket_age / 1000) > ticket_data.ticket_lifetime) { + session->internals.tls13_session_ticket_renew = 1; + _gnutls13_ticket_data_destroy(&ticket_data); + return 0; + } + + ticket_nonce.data = ticket_data.ticket_nonce; + ticket_nonce.size = ticket_data.ticket_nonce_len; + ret = compute_psk_from_ticket(prf, ticket_data.rms, &ticket_nonce, &key); + if (ret < 0) { + session->internals.tls13_session_ticket_renew = 1; + _gnutls13_ticket_data_destroy(&ticket_data); + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + } + + _gnutls13_ticket_data_destroy(&ticket_data); + psk_kind = TICKET; + } + /* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */ - if (psk.identity.size > 0) { + if (psk.identity.size > 0 && psk_kind == 0) { char identity_str[psk.identity.size + 1]; memcpy(identity_str, psk.identity.data, psk.identity.size); identity_str[psk.identity.size] = 0; ret = _gnutls_psk_pwd_find_entry(session, identity_str, &key); - if (ret == 0) + if (ret == 0) { + psk_kind = PSK; psk_index = psk.selected_index; + prf = _gnutls_mac_to_entry(pskcred->tls13_binder_algo); + } + + session->internals.tls13_session_ticket_renew = 0; } } if (psk_index < 0) return 0; + /* Are session tickets enabled? */ + if (psk_kind == TICKET && !session->internals.session_ticket_enable) + return 0; + ret = _gnutls13_psk_ext_parser_find_binder(psk_parser, psk_index, &binder_recvd); if (ret < 0) return gnutls_assert_val(ret); - if (binder_recvd.size == 0) - return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); ret = _gnutls13_psk_ext_parser_deinit(&psk_parser, &data, (size_t *) &len); @@ -350,7 +496,10 @@ static int server_recv_params(gnutls_session_t session, } /* Compute the binder value for this PSK */ - prf = _gnutls_mac_to_entry(pskcred->tls13_binder_algo); + if (!prf) { + ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + goto cleanup; + } hash_size = prf->output_size; compute_psk_binder(GNUTLS_SERVER, prf, hash_size, hash_size, 0, 0, 0, &key, &full_client_hello, @@ -422,13 +571,7 @@ static int _gnutls_psk_send_params(gnutls_session_t session, _gnutls_get_cred(session, GNUTLS_CRD_PSK); } - /* - * If there are no PSK credentials, this extension is not applicable, - * so we return zero. - */ - return (cred ? - client_send_params(session, extdata, cred) : - 0); + return client_send_params(session, extdata, cred); } else { if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) return server_send_params(session, extdata); @@ -463,13 +606,7 @@ static int _gnutls_psk_recv_params(gnutls_session_t session, pskcred = (gnutls_psk_server_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); - /* - * If there are no PSK credentials, this extension is not applicable, - * so we return zero. - */ - return (pskcred ? - server_recv_params(session, data, len, pskcred) : - 0); + return server_recv_params(session, data, len, pskcred); } else { return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); } diff --git a/lib/ext/pre_shared_key.h b/lib/ext/pre_shared_key.h index 22f64a37c0..f517c13288 100644 --- a/lib/ext/pre_shared_key.h +++ b/lib/ext/pre_shared_key.h @@ -2,6 +2,7 @@ #define EXT_PRE_SHARED_KEY_H #include <hello_ext.h> +#include "tls13/session_ticket.h" extern const hello_ext_entry_st ext_pre_shared_key; diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c index 44070423d8..0e5cbf4463 100644 --- a/lib/ext/psk_ke_modes.c +++ b/lib/ext/psk_ke_modes.c @@ -21,6 +21,7 @@ */ #include "gnutls_int.h" +#include "tls13/session_ticket.h" #include <ext/psk_ke_modes.h> #define PSK_DHE_KE 1 @@ -59,8 +60,17 @@ psk_ke_modes_send_params(gnutls_session_t session, cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); + if (cred) + goto have_psk; - if (cred) { + /* + * No out-of-band PSKs - do we have a session ticket? + * We're not interested in the ticket itself. + */ + retval = _gnutls13_session_ticket_peek(session, NULL); + +have_psk: + if (cred || retval) { retval = send_params(extdata, PSK_DHE_KE); if (retval < 0) gnutls_assert_val(retval); diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c index 7e0a0b2f8d..38e78c42f8 100644 --- a/lib/ext/session_ticket.c +++ b/lib/ext/session_ticket.c @@ -38,13 +38,10 @@ #ifdef ENABLE_SESSION_TICKETS -#define KEY_NAME_SIZE 16 -#define CIPHER_KEY_SIZE 32 #define CIPHER GNUTLS_CIPHER_AES_256_CBC #define IV_SIZE 16 #define BLOCK_SIZE 16 -#define MAC_SECRET_SIZE 16 #define MAC_ALGO GNUTLS_MAC_SHA1 #define MAC_SIZE 20 /* HMAC-SHA1 */ @@ -74,29 +71,11 @@ const hello_ext_entry_st ext_mod_session_ticket = { .cannot_be_overriden = 1 }; -#define SESSION_KEY_SIZE (KEY_NAME_SIZE+CIPHER_KEY_SIZE+MAC_SECRET_SIZE) -#define NAME_POS (0) -#define KEY_POS (KEY_NAME_SIZE) -#define MAC_SECRET_POS (KEY_NAME_SIZE+CIPHER_KEY_SIZE) - typedef struct { - int session_ticket_enable; - int session_ticket_renew; - uint8_t *session_ticket; int session_ticket_len; - - uint8_t key[SESSION_KEY_SIZE]; } session_ticket_ext_st; -struct ticket_st { - uint8_t key_name[KEY_NAME_SIZE]; - uint8_t IV[IV_SIZE]; - uint8_t *encrypted_state; - uint16_t encrypted_state_len; - uint8_t mac[MAC_SIZE]; -}; - static int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket, uint8_t * digest) @@ -124,7 +103,7 @@ int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket, } static int -decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, +decrypt_ticket(gnutls_session_t session, struct ticket_st *ticket) { cipher_hd_st cipher_hd; @@ -134,7 +113,7 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, int ret; /* Check the integrity of ticket */ - mac_secret.data = (void *) &priv->key[MAC_SECRET_POS]; + mac_secret.data = (void *) &session->key.session_ticket_key[MAC_SECRET_POS]; mac_secret.size = MAC_SECRET_SIZE; ret = digest_ticket(&mac_secret, ticket, cmac); if (ret < 0) @@ -147,7 +126,7 @@ decrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); /* Decrypt encrypted_state */ - key.data = (void *) &priv->key[KEY_POS]; + key.data = (void *) &session->key.session_ticket_key[KEY_POS]; key.size = CIPHER_KEY_SIZE; IV.data = ticket->IV; IV.size = IV_SIZE; @@ -202,7 +181,7 @@ cleanup: } static int -encrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, +encrypt_ticket(gnutls_session_t session, struct ticket_st *ticket) { cipher_hd_st cipher_hd; @@ -230,7 +209,7 @@ encrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, memcpy(encrypted_state.data, state.data, state.size); /* Encrypt state */ - key.data = (void *) &priv->key[KEY_POS]; + key.data = (void *) &session->key.session_ticket_key[KEY_POS]; key.size = CIPHER_KEY_SIZE; IV.data = iv; IV.size = IV_SIZE; @@ -261,12 +240,12 @@ encrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv, /* Fill the ticket structure to compute MAC. */ - memcpy(ticket->key_name, &priv->key[NAME_POS], KEY_NAME_SIZE); + memcpy(ticket->key_name, &session->key.session_ticket_key[NAME_POS], KEY_NAME_SIZE); memcpy(ticket->IV, IV.data, IV.size); ticket->encrypted_state_len = encrypted_state.size; ticket->encrypted_state = encrypted_state.data; - mac_secret.data = &priv->key[MAC_SECRET_POS]; + mac_secret.data = &session->key.session_ticket_key[MAC_SECRET_POS]; mac_secret.size = MAC_SECRET_SIZE; ret = digest_ticket(&mac_secret, ticket, ticket->mac); if (ret < 0) { @@ -293,20 +272,9 @@ session_ticket_recv_params(gnutls_session_t session, const uint8_t * data, size_t _data_size) { ssize_t data_size = _data_size; - session_ticket_ext_st *priv = NULL; - gnutls_ext_priv_data_t epriv; int ret; - ret = - _gnutls_hello_ext_get_priv(session, - GNUTLS_EXTENSION_SESSION_TICKET, - &epriv); - if (ret < 0) { - return 0; - } - priv = epriv; - - if (!priv->session_ticket_enable) + if (!session->internals.session_ticket_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) { @@ -315,7 +283,7 @@ session_ticket_recv_params(gnutls_session_t session, /* The client requested a new session ticket. */ if (data_size == 0) { - priv->session_ticket_renew = 1; + session->internals.session_ticket_renew = 1; return 0; } @@ -333,9 +301,9 @@ session_ticket_recv_params(gnutls_session_t session, /* If the key name of the ticket does not match the one that we hold, issue a new ticket. */ if (memcmp - (ticket.key_name, &priv->key[NAME_POS], + (ticket.key_name, &session->key.session_ticket_key[NAME_POS], KEY_NAME_SIZE)) { - priv->session_ticket_renew = 1; + session->internals.session_ticket_renew = 1; return 0; } @@ -364,19 +332,19 @@ session_ticket_recv_params(gnutls_session_t session, memcpy(ticket.encrypted_state, encrypted_state, ticket.encrypted_state_len); - ret = decrypt_ticket(session, priv, &ticket); + ret = decrypt_ticket(session, &ticket); gnutls_free(ticket.encrypted_state); ticket.encrypted_state = NULL; if (ret < 0) { - priv->session_ticket_renew = 1; + session->internals.session_ticket_renew = 1; return 0; } } else { /* Client */ if (data_size == 0) { - priv->session_ticket_renew = 1; + session->internals.session_ticket_renew = 1; return 0; } } @@ -402,11 +370,11 @@ session_ticket_send_params(gnutls_session_t session, if (ret >= 0) priv = epriv; - if (priv == NULL || !priv->session_ticket_enable) + if (priv == NULL || !session->internals.session_ticket_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER) { - if (priv && priv->session_ticket_renew) { + if (priv && session->internals.session_ticket_renew) { return GNUTLS_E_INT_RET_0; } } else { @@ -422,7 +390,7 @@ session_ticket_send_params(gnutls_session_t session, return GNUTLS_E_INT_RET_0; /* previous data had session tickets disabled. Don't advertize. Ignore. */ - if (!priv->session_ticket_enable) + if (!session->internals.session_ticket_enable) return 0; if (priv->session_ticket_len > 0) { @@ -458,7 +426,6 @@ session_ticket_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps) BUFFER_APPEND_PFX4(ps, priv->session_ticket, priv->session_ticket_len); - BUFFER_APPEND_NUM(ps, priv->session_ticket_enable); return 0; } @@ -480,7 +447,6 @@ session_ticket_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv) BUFFER_POP_DATUM(ps, &ticket); priv->session_ticket = ticket.data; priv->session_ticket_len = ticket.size; - BUFFER_POP_NUM(ps, priv->session_ticket_enable); epriv = priv; *_priv = epriv; @@ -546,25 +512,12 @@ int gnutls_session_ticket_key_generate(gnutls_datum_t * key) **/ int gnutls_session_ticket_enable_client(gnutls_session_t session) { - session_ticket_ext_st *priv = NULL; - gnutls_ext_priv_data_t epriv; - if (!session) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - priv = gnutls_calloc(1, sizeof(*priv)); - if (priv == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - priv->session_ticket_enable = 1; - epriv = priv; - - _gnutls_hello_ext_set_priv(session, - GNUTLS_EXTENSION_SESSION_TICKET, - epriv); + session->internals.session_ticket_enable = 1; return 0; } @@ -588,31 +541,21 @@ int gnutls_session_ticket_enable_server(gnutls_session_t session, const gnutls_datum_t * key) { - session_ticket_ext_st *priv = NULL; - gnutls_ext_priv_data_t epriv; - if (!session || !key || key->size != SESSION_KEY_SIZE) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - priv = gnutls_calloc(1, sizeof(*priv)); - if (priv == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - epriv = priv; - - memcpy(&priv->key, key->data, key->size); - priv->session_ticket_enable = 1; - - _gnutls_hello_ext_set_priv(session, - GNUTLS_EXTENSION_SESSION_TICKET, - epriv); + memcpy(session->key.session_ticket_key, key->data, key->size); + session->internals.session_ticket_enable = 1; + session->internals.tls13_session_ticket_renew = 1; return 0; } +/* + * Return zero if session tickets haven't been enabled. + */ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) { mbuffer_st *bufel = NULL; @@ -621,20 +564,12 @@ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) int ret; struct ticket_st ticket; uint16_t ticket_len; - session_ticket_ext_st *priv = NULL; - gnutls_ext_priv_data_t epriv; uint16_t epoch_saved = session->security_parameters.epoch_write; if (again == 0) { - ret = - _gnutls_hello_ext_get_priv(session, - GNUTLS_EXTENSION_SESSION_TICKET, - &epriv); - if (ret < 0) + if (!session->internals.session_ticket_enable) return 0; - priv = epriv; - - if (!priv->session_ticket_renew) + if (!session->internals.session_ticket_renew) return 0; /* XXX: Temporarily set write algorithms to be used. @@ -653,7 +588,7 @@ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) session->security_parameters.epoch_write = session->security_parameters.epoch_next; - ret = encrypt_ticket(session, priv, &ticket); + ret = encrypt_ticket(session, &ticket); session->security_parameters.epoch_write = epoch_saved; if (ret < 0) { gnutls_assert(); @@ -706,6 +641,9 @@ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); } +/* + * Return zero if session ticets haven't been enabled. + */ int _gnutls_recv_new_session_ticket(gnutls_session_t session) { uint8_t *p; @@ -716,17 +654,9 @@ int _gnutls_recv_new_session_ticket(gnutls_session_t session) session_ticket_ext_st *priv = NULL; gnutls_ext_priv_data_t epriv; - ret = - _gnutls_hello_ext_get_priv(session, - GNUTLS_EXTENSION_SESSION_TICKET, - &epriv); - if (ret < 0) { - gnutls_assert(); + if (!session->internals.session_ticket_enable) return 0; - } - priv = epriv; - - if (!priv->session_ticket_renew) + if (!session->internals.session_ticket_renew) return 0; /* This is the last flight and peer cannot be sure @@ -764,6 +694,16 @@ int _gnutls_recv_new_session_ticket(gnutls_session_t session) DECR_LENGTH_COM(data_size, ticket_len, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); + + ret = + _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SESSION_TICKET, + &epriv); + if (ret < 0) { + gnutls_assert(); + return 0; + } + priv = epriv; priv->session_ticket = gnutls_realloc_fast(priv->session_ticket, ticket_len); if (!priv->session_ticket) { @@ -789,6 +729,11 @@ int _gnutls_recv_new_session_ticket(gnutls_session_t session) } ret = 0; + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SESSION_TICKET, + epriv); + error: _gnutls_buffer_clear(&buf); diff --git a/lib/ext/session_ticket.h b/lib/ext/session_ticket.h index c00c3f6b7e..e744dd687b 100644 --- a/lib/ext/session_ticket.h +++ b/lib/ext/session_ticket.h @@ -25,9 +25,26 @@ #include <hello_ext.h> +#define KEY_NAME_SIZE 16 +#define IV_SIZE 16 +#define MAC_SIZE 20 /* HMAC-SHA1 */ + +struct ticket_st { + uint8_t key_name[KEY_NAME_SIZE]; + uint8_t IV[IV_SIZE]; + uint8_t *encrypted_state; + uint16_t encrypted_state_len; + uint8_t mac[MAC_SIZE]; +}; + extern const hello_ext_entry_st ext_mod_session_ticket; int _gnutls_send_new_session_ticket(gnutls_session_t session, int again); int _gnutls_recv_new_session_ticket(gnutls_session_t session); +int _gnutls_encrypt_session_ticket(gnutls_session_t session, + struct ticket_st *ticket); +int _gnutls_decrypt_session_ticket(gnutls_session_t session, + struct ticket_st *ticket); + #endif |