diff options
Diffstat (limited to 'lib/ext')
-rw-r--r-- | lib/ext/session_ticket.c | 133 |
1 files changed, 67 insertions, 66 deletions
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c index d2a15e5eb3..177135e642 100644 --- a/lib/ext/session_ticket.c +++ b/lib/ext/session_ticket.c @@ -34,16 +34,9 @@ #include <hello_ext.h> #include <constate.h> #include <dtls.h> +#include "stek.h" #include "db.h" -/* They are restricted by TICKET_CIPHER_KEY_SIZE and TICKET_MAC_SECRET_SIZE */ -#define CIPHER GNUTLS_CIPHER_AES_256_CBC -#define IV_SIZE 16 -#define BLOCK_SIZE 16 - -#define MAC_ALGO GNUTLS_MAC_SHA1 -#define MAC_SIZE 20 /* HMAC-SHA1 */ - static int session_ticket_recv_params(gnutls_session_t session, const uint8_t * data, size_t data_size); @@ -70,23 +63,11 @@ const hello_ext_entry_st ext_mod_session_ticket = { .cannot_be_overriden = 1 }; -#define NAME_POS (0) -#define KEY_POS (TICKET_KEY_NAME_SIZE) -#define MAC_SECRET_POS (TICKET_KEY_NAME_SIZE+TICKET_CIPHER_KEY_SIZE) - typedef struct { uint8_t *session_ticket; int session_ticket_len; } session_ticket_ext_st; -struct ticket_st { - uint8_t key_name[TICKET_KEY_NAME_SIZE]; - uint8_t IV[IV_SIZE]; - uint8_t *encrypted_state; - uint16_t encrypted_state_len; - uint8_t mac[MAC_SIZE]; -}; - static void deinit_ticket(struct ticket_st *ticket) { @@ -111,9 +92,9 @@ unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket) memcpy(ticket->key_name, data, TICKET_KEY_NAME_SIZE); data += TICKET_KEY_NAME_SIZE; - DECR_LEN(data_size, IV_SIZE); - memcpy(ticket->IV, data, IV_SIZE); - data += IV_SIZE; + DECR_LEN(data_size, TICKET_IV_SIZE); + memcpy(ticket->IV, data, TICKET_IV_SIZE); + data += TICKET_IV_SIZE; DECR_LEN(data_size, 2); ticket->encrypted_state_len = _gnutls_read_uint16(data); @@ -124,8 +105,8 @@ unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket) DECR_LEN(data_size, ticket->encrypted_state_len); data += ticket->encrypted_state_len; - DECR_LEN(data_size, MAC_SIZE); - memcpy(ticket->mac, data, MAC_SIZE); + DECR_LEN(data_size, TICKET_MAC_SIZE); + memcpy(ticket->mac, data, TICKET_MAC_SIZE); ticket->encrypted_state = gnutls_malloc(ticket->encrypted_state_len); @@ -149,8 +130,8 @@ pack_ticket(const struct ticket_st *ticket, gnutls_datum_t *ticket_data) memcpy(p, ticket->key_name, TICKET_KEY_NAME_SIZE); p += TICKET_KEY_NAME_SIZE; - memcpy(p, ticket->IV, IV_SIZE); - p += IV_SIZE; + memcpy(p, ticket->IV, TICKET_IV_SIZE); + p += TICKET_IV_SIZE; _gnutls_write_uint16(ticket->encrypted_state_len, p); p += 2; @@ -158,7 +139,7 @@ pack_ticket(const struct ticket_st *ticket, gnutls_datum_t *ticket_data) memcpy(p, ticket->encrypted_state, ticket->encrypted_state_len); p += ticket->encrypted_state_len; - memcpy(p, ticket->mac, MAC_SIZE); + memcpy(p, ticket->mac, TICKET_MAC_SIZE); } static @@ -169,7 +150,7 @@ int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket, uint16_t length16; int ret; - ret = _gnutls_mac_init(&digest_hd, mac_to_entry(MAC_ALGO), + ret = _gnutls_mac_init(&digest_hd, mac_to_entry(TICKET_MAC_ALGO), key->data, key->size); if (ret < 0) { gnutls_assert(); @@ -177,7 +158,7 @@ int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket, } _gnutls_mac(&digest_hd, ticket->key_name, TICKET_KEY_NAME_SIZE); - _gnutls_mac(&digest_hd, ticket->IV, IV_SIZE); + _gnutls_mac(&digest_hd, ticket->IV, TICKET_IV_SIZE); length16 = _gnutls_conv_uint16(ticket->encrypted_state_len); _gnutls_mac(&digest_hd, &length16, 2); _gnutls_mac(&digest_hd, ticket->encrypted_state, @@ -193,50 +174,60 @@ _gnutls_decrypt_session_ticket(gnutls_session_t session, gnutls_datum_t *state) { cipher_hd_st cipher_hd; - gnutls_datum_t key, IV, mac_secret; - uint8_t cmac[MAC_SIZE]; + gnutls_datum_t IV; + gnutls_datum_t stek_key_name, stek_cipher_key, stek_mac_key; + uint8_t cmac[TICKET_MAC_SIZE]; struct ticket_st ticket; int ret; - /* If the key name of the ticket does not match the one that we - hold, issue a new ticket. */ - if (ticket_data->size < TICKET_KEY_NAME_SIZE || - memcmp(ticket_data->data, &session->key.session_ticket_key[NAME_POS], - TICKET_KEY_NAME_SIZE)) + /* callers must have that checked */ + assert(!(session->internals.flags & GNUTLS_NO_TICKETS)); + + /* Retrieve ticket decryption keys */ + if (_gnutls_get_session_ticket_decryption_key(session, + ticket_data, + &stek_key_name, + &stek_mac_key, + &stek_cipher_key) < 0) return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); ret = unpack_ticket(ticket_data, &ticket); if (ret < 0) return ret; + /* If the key name of the ticket does not match the one that is currently active, + issue a new ticket. */ + if (memcmp + (ticket.key_name, stek_key_name.data, + stek_key_name.size)) { + ret = GNUTLS_E_DECRYPTION_FAILED; + goto cleanup; + } + /* Check the integrity of ticket */ - mac_secret.data = (void *) &session->key.session_ticket_key[MAC_SECRET_POS]; - mac_secret.size = TICKET_MAC_SECRET_SIZE; - ret = digest_ticket(&mac_secret, &ticket, cmac); + ret = digest_ticket(&stek_mac_key, &ticket, cmac); if (ret < 0) { gnutls_assert(); goto cleanup; } - if (memcmp(ticket.mac, cmac, MAC_SIZE)) { + if (memcmp(ticket.mac, cmac, TICKET_MAC_SIZE)) { ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); goto cleanup; } - if (ticket.encrypted_state_len % BLOCK_SIZE != 0) { + if (ticket.encrypted_state_len % TICKET_BLOCK_SIZE != 0) { ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); goto cleanup; } /* Decrypt encrypted_state */ - key.data = (void *) &session->key.session_ticket_key[KEY_POS]; - key.size = TICKET_CIPHER_KEY_SIZE; IV.data = ticket.IV; - IV.size = IV_SIZE; + IV.size = TICKET_IV_SIZE; ret = _gnutls_cipher_init(&cipher_hd, - cipher_to_entry(CIPHER), - &key, &IV, 0); + cipher_to_entry(TICKET_CIPHER), + &stek_cipher_key, &IV, 0); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -272,32 +263,39 @@ _gnutls_encrypt_session_ticket(gnutls_session_t session, gnutls_datum_t *ticket_data) { cipher_hd_st cipher_hd; - gnutls_datum_t key, IV; + gnutls_datum_t IV; gnutls_datum_t encrypted_state = {NULL,0}; - uint8_t iv[IV_SIZE]; - gnutls_datum_t mac_secret; + uint8_t iv[TICKET_IV_SIZE]; + gnutls_datum_t stek_cipher_key, stek_mac_key, stek_key_name; struct ticket_st ticket; int ret; - encrypted_state.size = ((state->size + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE; - ticket_data->size = TICKET_KEY_NAME_SIZE + IV_SIZE + 2 + - encrypted_state.size + MAC_SIZE; + encrypted_state.size = ((state->size + TICKET_BLOCK_SIZE - 1) / TICKET_BLOCK_SIZE) * TICKET_BLOCK_SIZE; + ticket_data->size = TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2 + + encrypted_state.size + TICKET_MAC_SIZE; ticket_data->data = gnutls_calloc(1, ticket_data->size); if (!ticket_data->data) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } - encrypted_state.data = ticket_data->data + TICKET_KEY_NAME_SIZE + IV_SIZE + 2; + encrypted_state.data = ticket_data->data + TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2; memcpy(encrypted_state.data, state->data, state->size); + /* Retrieve ticket encryption keys */ + if (_gnutls_get_session_ticket_encryption_key(session, + &stek_key_name, + &stek_mac_key, + &stek_cipher_key) < 0) { + ret = GNUTLS_E_ENCRYPTION_FAILED; + goto cleanup; + } + /* Encrypt state */ - key.data = (void *) &session->key.session_ticket_key[KEY_POS]; - key.size = TICKET_CIPHER_KEY_SIZE; IV.data = iv; - IV.size = IV_SIZE; + IV.size = TICKET_IV_SIZE; - ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, IV_SIZE); + ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, TICKET_IV_SIZE); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -305,8 +303,8 @@ _gnutls_encrypt_session_ticket(gnutls_session_t session, ret = _gnutls_cipher_init(&cipher_hd, - cipher_to_entry(CIPHER), - &key, &IV, 1); + cipher_to_entry(TICKET_CIPHER), + &stek_cipher_key, &IV, 1); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -321,14 +319,12 @@ _gnutls_encrypt_session_ticket(gnutls_session_t session, /* Fill the ticket structure to compute MAC. */ - memcpy(ticket.key_name, &session->key.session_ticket_key[NAME_POS], TICKET_KEY_NAME_SIZE); + memcpy(ticket.key_name, stek_key_name.data, stek_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 = &session->key.session_ticket_key[MAC_SECRET_POS]; - mac_secret.size = TICKET_MAC_SECRET_SIZE; - ret = digest_ticket(&mac_secret, &ticket, ticket.mac); + ret = digest_ticket(&stek_mac_key, &ticket, ticket.mac); if (ret < 0) { gnutls_assert(); goto cleanup2; @@ -606,12 +602,17 @@ int gnutls_session_ticket_enable_server(gnutls_session_t session, const gnutls_datum_t * key) { - if (!session || !key || key->size != TICKET_MASTER_KEY_SIZE) { + int ret; + + if (!session || !key || key->size != TICKET_MASTER_KEY_SIZE || !key->data) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - memcpy(session->key.session_ticket_key, key->data, key->size); + ret = _gnutls_initialize_session_ticket_key_rotation(session, key); + if (ret < 0) + return gnutls_assert_val(ret); + session->internals.flags &= ~GNUTLS_NO_TICKETS; return 0; |