summaryrefslogtreecommitdiff
path: root/lib/ext
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ext')
-rw-r--r--lib/ext/pre_shared_key.c209
-rw-r--r--lib/ext/pre_shared_key.h1
-rw-r--r--lib/ext/psk_ke_modes.c12
-rw-r--r--lib/ext/session_ticket.c149
-rw-r--r--lib/ext/session_ticket.h17
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