|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017-2018 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos, Ander Juaristi
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include "extv.h"
|
|
Packit Service |
4684c1 |
#include "handshake.h"
|
|
Packit Service |
4684c1 |
#include "mbuffers.h"
|
|
Packit Service |
4684c1 |
#include "ext/pre_shared_key.h"
|
|
Packit Service |
4684c1 |
#include "ext/session_ticket.h"
|
|
Packit Service |
4684c1 |
#include "ext/early_data.h"
|
|
Packit Service |
4684c1 |
#include "auth/cert.h"
|
|
Packit Service |
4684c1 |
#include "tls13/session_ticket.h"
|
|
Packit Service |
4684c1 |
#include "session_pack.h"
|
|
Packit Service |
4684c1 |
#include "db.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
pack_ticket(gnutls_session_t session, tls13_ticket_st *ticket, gnutls_datum_t *packed)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t *p;
|
|
Packit Service |
4684c1 |
gnutls_datum_t state;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_session_pack(session, &state);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
packed->size = 2 + 4 + 4 +
|
|
Packit Service |
4684c1 |
1 + ticket->prf->output_size +
|
|
Packit Service |
4684c1 |
1 + ticket->nonce_size + 2 + state.size + 12;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
packed->data = gnutls_malloc(packed->size);
|
|
Packit Service |
4684c1 |
if (!packed->data) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = packed->data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_write_uint16(ticket->prf->id, p);
|
|
Packit Service |
4684c1 |
p += 2;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(ticket->age_add, p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(ticket->lifetime, p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
*p = ticket->prf->output_size;
|
|
Packit Service |
4684c1 |
p += 1;
|
|
Packit Service |
4684c1 |
memcpy(p, ticket->resumption_master_secret, ticket->prf->output_size);
|
|
Packit Service |
4684c1 |
p += ticket->prf->output_size;
|
|
Packit Service |
4684c1 |
*p = ticket->nonce_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p += 1;
|
|
Packit Service |
4684c1 |
memcpy(p, ticket->nonce, ticket->nonce_size);
|
|
Packit Service |
4684c1 |
p += ticket->nonce_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_write_uint16(state.size, p);
|
|
Packit Service |
4684c1 |
p += 2;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(p, state.data, state.size);
|
|
Packit Service |
4684c1 |
p += state.size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32((uint64_t) ticket->creation_time.tv_sec >> 32, p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(ticket->creation_time.tv_sec & 0xFFFFFFFF, p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(ticket->creation_time.tv_nsec, p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_free(state.data);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st *data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint32_t age_add, lifetime;
|
|
Packit Service |
4684c1 |
struct timespec creation_time;
|
|
Packit Service |
4684c1 |
uint8_t resumption_master_secret[MAX_HASH_SIZE];
|
|
Packit Service |
4684c1 |
size_t resumption_master_secret_size;
|
|
Packit Service |
4684c1 |
uint8_t nonce[UINT8_MAX];
|
|
Packit Service |
4684c1 |
size_t nonce_size;
|
|
Packit Service |
4684c1 |
gnutls_datum_t state;
|
|
Packit Service |
4684c1 |
gnutls_mac_algorithm_t kdf;
|
|
Packit Service |
4684c1 |
const mac_entry_st *prf;
|
|
Packit Service |
4684c1 |
uint8_t *p;
|
|
Packit Service |
4684c1 |
size_t len;
|
|
Packit Service |
4684c1 |
uint64_t v;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(packed == NULL || data == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(data, 0, sizeof(*data));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
p = packed->data;
|
|
Packit Service |
4684c1 |
len = packed->size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 2);
|
|
Packit Service |
4684c1 |
kdf = _gnutls_read_uint16(p);
|
|
Packit Service |
4684c1 |
p += 2;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Check if the MAC ID we got is valid */
|
|
Packit Service |
4684c1 |
prf = _gnutls_mac_to_entry(kdf);
|
|
Packit Service |
4684c1 |
if (prf == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Read the ticket age add and the ticket lifetime */
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 4);
|
|
Packit Service |
4684c1 |
age_add = _gnutls_read_uint32(p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 4);
|
|
Packit Service |
4684c1 |
lifetime = _gnutls_read_uint32(p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Check if the whole ticket is large enough,
|
|
Packit Service |
4684c1 |
* and read the resumption master secret
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 1);
|
|
Packit Service |
4684c1 |
resumption_master_secret_size = *p;
|
|
Packit Service |
4684c1 |
p += 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Check if the size of resumption_master_secret matches the PRF */
|
|
Packit Service |
4684c1 |
if (resumption_master_secret_size != prf->output_size)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, resumption_master_secret_size);
|
|
Packit Service |
4684c1 |
memcpy(resumption_master_secret, p, resumption_master_secret_size);
|
|
Packit Service |
4684c1 |
p += resumption_master_secret_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Read the ticket nonce */
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 1);
|
|
Packit Service |
4684c1 |
nonce_size = *p;
|
|
Packit Service |
4684c1 |
p += 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, nonce_size);
|
|
Packit Service |
4684c1 |
memcpy(nonce, p, nonce_size);
|
|
Packit Service |
4684c1 |
p += nonce_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 2);
|
|
Packit Service |
4684c1 |
state.size = _gnutls_read_uint16(p);
|
|
Packit Service |
4684c1 |
p += 2;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, state.size);
|
|
Packit Service |
4684c1 |
state.data = p;
|
|
Packit Service |
4684c1 |
p += state.size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(len, 12);
|
|
Packit Service |
4684c1 |
v = _gnutls_read_uint32(p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
creation_time.tv_sec = (v << 32) | _gnutls_read_uint32(p);
|
|
Packit Service |
4684c1 |
p += 4;
|
|
Packit Service |
4684c1 |
creation_time.tv_nsec = _gnutls_read_uint32(p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_session_unpack(session, &state);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* No errors - Now return all the data to the caller */
|
|
Packit Service |
4684c1 |
data->prf = prf;
|
|
Packit Service |
4684c1 |
memcpy(data->resumption_master_secret, resumption_master_secret,
|
|
Packit Service |
4684c1 |
resumption_master_secret_size);
|
|
Packit Service |
4684c1 |
memcpy(data->nonce, nonce, nonce_size);
|
|
Packit Service |
4684c1 |
data->nonce_size = nonce_size;
|
|
Packit Service |
4684c1 |
data->age_add = age_add;
|
|
Packit Service |
4684c1 |
data->lifetime = lifetime;
|
|
Packit Service |
4684c1 |
memcpy(&data->creation_time, &creation_time, sizeof(struct timespec));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
generate_session_ticket(gnutls_session_t session, tls13_ticket_st *ticket)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t packed = { NULL, 0 };
|
|
Packit Service |
4684c1 |
struct timespec now;
|
|
Packit Service |
4684c1 |
tls13_ticket_st ticket_data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_gettime(&now;;
|
|
Packit Service |
4684c1 |
if (session->internals.resumed != RESUME_FALSE) {
|
|
Packit Service |
4684c1 |
/* If we are resuming ensure that we don't extend the lifetime
|
|
Packit Service |
4684c1 |
* of the ticket past the original session expiration time */
|
|
Packit Service |
4684c1 |
if (now.tv_sec >= session->security_parameters.timestamp + session->internals.expire_time)
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INT_RET_0; /* don't send ticket */
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
ticket->lifetime = session->security_parameters.timestamp +
|
|
Packit Service |
4684c1 |
session->internals.expire_time - now.tv_sec;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
/* Set ticket lifetime to the default expiration time */
|
|
Packit Service |
4684c1 |
ticket->lifetime = session->internals.expire_time;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Generate a random 32-bit ticket nonce */
|
|
Packit Service |
4684c1 |
ticket->nonce_size = 4;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret = gnutls_rnd(GNUTLS_RND_NONCE,
|
|
Packit Service |
4684c1 |
ticket->nonce, ticket->nonce_size)) < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret = gnutls_rnd(GNUTLS_RND_NONCE, &ticket->age_add, sizeof(uint32_t))) < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
/* This is merely to produce the same binder value on
|
|
Packit Service |
4684c1 |
* different endian architectures. */
|
|
Packit Service |
4684c1 |
#ifdef WORDS_BIGENDIAN
|
|
Packit Service |
4684c1 |
ticket->age_add = bswap_32(ticket->age_add);
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ticket->prf = session->security_parameters.prf;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Encrypt the ticket and place the result in ticket->ticket */
|
|
Packit Service |
4684c1 |
ticket_data.lifetime = ticket->lifetime;
|
|
Packit Service |
4684c1 |
ticket_data.age_add = ticket->age_add;
|
|
Packit Service |
4684c1 |
memcpy(&ticket_data.creation_time, &now, sizeof(struct timespec));
|
|
Packit Service |
4684c1 |
memcpy(ticket_data.nonce, ticket->nonce, ticket->nonce_size);
|
|
Packit Service |
4684c1 |
ticket_data.nonce_size = ticket->nonce_size;
|
|
Packit Service |
4684c1 |
ticket_data.prf = ticket->prf;
|
|
Packit Service |
4684c1 |
memcpy(&ticket_data.resumption_master_secret,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_rms,
|
|
Packit Service |
4684c1 |
ticket->prf->output_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = pack_ticket(session, &ticket_data, &packed);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_encrypt_session_ticket(session, &packed, &ticket->ticket);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&packed);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int append_nst_extension(void *ctx, gnutls_buffer_st *buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_session_t session = ctx;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(session->internals.flags & GNUTLS_ENABLE_EARLY_DATA))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_prefix(buf, 32,
|
|
Packit Service |
4684c1 |
session->security_parameters.
|
|
Packit Service |
4684c1 |
max_early_data_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = 0;
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = NULL;
|
|
Packit Service |
4684c1 |
gnutls_buffer_st buf;
|
|
Packit Service |
4684c1 |
tls13_ticket_st ticket;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Client does not send a NewSessionTicket */
|
|
Packit Service |
4684c1 |
if (unlikely(session->security_parameters.entity == GNUTLS_CLIENT))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Session resumption has not been enabled */
|
|
Packit Service |
4684c1 |
if (session->internals.flags & GNUTLS_NO_TICKETS)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If we received the psk_key_exchange_modes extension which
|
|
Packit Service |
4684c1 |
* does not have overlap with the server configuration, don't
|
|
Packit Service |
4684c1 |
* send a session ticket */
|
|
Packit Service |
4684c1 |
if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (again == 0) {
|
|
Packit Service |
4684c1 |
for (i=0;i
|
|
Packit Service |
4684c1 |
unsigned init_pos;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&ticket, 0, sizeof(tls13_ticket_st));
|
|
Packit Service |
4684c1 |
bufel = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_init_handshake_mbuffer(&buf;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = generate_session_ticket(session, &ticket);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_INT_RET_0) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(0);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.lifetime);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.age_add);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* append ticket_nonce */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data_prefix(&buf, 8, ticket.nonce, ticket.nonce_size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* append ticket */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data_prefix(&buf, 16, ticket.ticket.data, ticket.ticket.size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&ticket.ticket);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* append extensions */
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append_init(&buf;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
init_pos = ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append(&buf, ext_mod_early_data.tls_id, session,
|
|
Packit Service |
4684c1 |
(extv_append_func)append_nst_extension);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append_final(&buf, init_pos, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bufel = _gnutls_buffer_to_mbuffer(&buf;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_send_handshake2(session, bufel,
|
|
Packit Service |
4684c1 |
GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 1);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_handshake_io_write_flush(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&ticket.ticket);
|
|
Packit Service |
4684c1 |
_mbuffer_xfree(&bufel);
|
|
Packit Service |
4684c1 |
_gnutls_buffer_clear(&buf;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int parse_nst_extension(void *ctx, unsigned tls_id, const unsigned char *data, unsigned data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_session_t session = ctx;
|
|
Packit Service |
4684c1 |
if (tls_id == ext_mod_early_data.tls_id) {
|
|
Packit Service |
4684c1 |
if (data_size < 4)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_TLS_PACKET_DECODING_ERROR);
|
|
Packit Service |
4684c1 |
session->security_parameters.max_early_data_size =
|
|
Packit Service |
4684c1 |
_gnutls_read_uint32(data);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
uint8_t value;
|
|
Packit Service |
4684c1 |
tls13_ticket_st *ticket = &session->internals.tls13_ticket;
|
|
Packit Service |
4684c1 |
gnutls_datum_t t;
|
|
Packit Service |
4684c1 |
size_t val;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(buf == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&ticket->ticket);
|
|
Packit Service |
4684c1 |
memset(ticket, 0, sizeof(tls13_ticket_st));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ticket_lifetime */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
ticket->lifetime = val;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ticket_age_add */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
ticket->age_add = val;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ticket_nonce */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_pop_prefix8(buf, &value, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ticket->nonce_size = value;
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_pop_data(buf, ticket->nonce, ticket->nonce_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ticket */
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_pop_datum_prefix16(buf, &t);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(ticket->ticket.data);
|
|
Packit Service |
4684c1 |
ret = _gnutls_set_datum(&ticket->ticket, t.data, t.size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Extensions */
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_parse(session, parse_nst_extension, buf->data, buf->length);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Record the ticket arrival time */
|
|
Packit Service |
4684c1 |
gnutls_gettime(&ticket->arrival_time);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Parse the ticket in 'data' and return the resumption master secret
|
|
Packit Service |
4684c1 |
* and the KDF ID associated to it.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls13_unpack_session_ticket(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_datum_t *data,
|
|
Packit Service |
4684c1 |
tls13_ticket_st *ticket_data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t decrypted = { NULL, 0 };
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(data == NULL || ticket_data == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Check MAC and decrypt ticket */
|
|
Packit Service |
4684c1 |
ret = _gnutls_decrypt_session_ticket(session, data, &decrypted);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Return ticket parameters */
|
|
Packit Service |
4684c1 |
ret = unpack_ticket(session, &decrypted, ticket_data);
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&decrypted);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_check_resumed_params(session);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|