summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-05-15 10:10:20 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-05-26 04:12:04 +0000
commit9e197e0cc1ffe9186bcdf1aff925316d93f232a2 (patch)
tree5535b6f9d34ede2345e148fc73c7358eb70e752a
parent34620f5b9291f5afb56012e04302df6006b7faf5 (diff)
downloadgnutls-9e197e0cc1ffe9186bcdf1aff925316d93f232a2.tar.gz
handshake: store session parameters in TLS1.3 ticket
This allows a TLS1.3 server to obtain certificate or other information from the client on a resumed session. Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/auth.c9
-rw-r--r--lib/constate.c10
-rw-r--r--lib/ext/session_ticket.c10
-rw-r--r--lib/handshake-tls13.c6
-rw-r--r--lib/session_pack.c1
-rw-r--r--lib/tls13/session_ticket.c67
6 files changed, 77 insertions, 26 deletions
diff --git a/lib/auth.c b/lib/auth.c
index 1ee2d72476..4bdedda38b 100644
--- a/lib/auth.c
+++ b/lib/auth.c
@@ -193,6 +193,9 @@ gnutls_credentials_get(gnutls_session_t session,
* %GNUTLS_KX_RSA, %GNUTLS_KX_DHE_RSA), the same function are to be
* used to access the authentication data.
*
+ * Note that on resumed sessions, this function returns the schema
+ * used in the original session authentication.
+ *
* Returns: The type of credentials for the current authentication
* schema, a #gnutls_credentials_type_t type.
**/
@@ -212,6 +215,9 @@ gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session)
* The returned information is to be used to distinguish the function used
* to access authentication data.
*
+ * Note that on resumed sessions, this function returns the schema
+ * used in the original session authentication.
+ *
* Returns: The type of credentials for the server authentication
* schema, a #gnutls_credentials_type_t type.
**/
@@ -229,6 +235,9 @@ gnutls_auth_server_get_type(gnutls_session_t session)
* The returned information is to be used to distinguish the function used
* to access authentication data.
*
+ * Note that on resumed sessions, this function returns the schema
+ * used in the original session authentication.
+ *
* Returns: The type of credentials for the client authentication
* schema, a #gnutls_credentials_type_t type.
**/
diff --git a/lib/constate.c b/lib/constate.c
index ecfd53c494..cdf9ed6479 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -647,7 +647,9 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch, hs_stage_t
return 0;
}
-
+/* This copies the session values which apply to subsequent/resumed
+ * sessions. Under TLS 1.3, these values are items which are not
+ * negotiated on the subsequent session. */
#define CPY_COMMON(tls13_sem) \
if (!tls13_sem) { \
dst->cs = src->cs; \
@@ -661,11 +663,11 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch, hs_stage_t
dst->prf = src->prf; \
dst->grp = src->grp; \
dst->pversion = src->pversion; \
+ memcpy( dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE); \
+ dst->session_id_size = src->session_id_size; \
+ dst->timestamp = src->timestamp; \
} \
- memcpy( dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE); \
- dst->session_id_size = src->session_id_size; \
dst->cert_type = src->cert_type; \
- dst->timestamp = src->timestamp; \
dst->client_auth_type = src->client_auth_type; \
dst->server_auth_type = src->server_auth_type
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
index 2bcc4cd984..2c91c9ec2d 100644
--- a/lib/ext/session_ticket.c
+++ b/lib/ext/session_ticket.c
@@ -594,9 +594,13 @@ int gnutls_session_ticket_enable_client(gnutls_session_t session)
* @key: key to encrypt session parameters.
*
* Request that the server should attempt session resumption using
- * SessionTicket. @key must be initialized with
- * gnutls_session_ticket_key_generate(), and should be overwritten
- * using gnutls_memset() before being released.
+ * session tickets, i.e., by delegating storage to the client.
+ * @key must be initialized using gnutls_session_ticket_key_generate().
+ * To avoid leaking that key, use gnutls_memset() prior to
+ * releasing it.
+ *
+ * The default ticket expiration time can be overriden using
+ * gnutls_db_set_cache_expiration().
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
* error code.
diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c
index ef7862f9e2..effc260566 100644
--- a/lib/handshake-tls13.c
+++ b/lib/handshake-tls13.c
@@ -375,8 +375,12 @@ int _gnutls13_handshake_server(gnutls_session_t session)
generate_ap_traffic_keys(session);
STATE = STATE111;
IMED_RET("generate app keys", ret, 0);
+
+ if (session->internals.resumed != RESUME_FALSE)
+ _gnutls_set_resumed_parameters(session);
/* fall through */
case STATE112:
+
ret = _gnutls13_send_session_ticket(session, AGAIN(STATE112));
STATE = STATE112;
IMED_RET("send session ticket", ret, 0);
@@ -393,8 +397,6 @@ int _gnutls13_handshake_server(gnutls_session_t session)
SAVE_TRANSCRIPT;
- if (session->internals.resumed != RESUME_FALSE)
- _gnutls_set_resumed_parameters(session);
return 0;
}
diff --git a/lib/session_pack.c b/lib/session_pack.c
index be4cdafc2d..dd8e6f885a 100644
--- a/lib/session_pack.c
+++ b/lib/session_pack.c
@@ -1088,6 +1088,7 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
session->internals.resumed_security_parameters.
server_auth_type);
+
if (session->internals.resumed_security_parameters.
max_record_recv_size == 0
|| session->internals.resumed_security_parameters.
diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c
index 4680a32d1a..25e067fc00 100644
--- a/lib/tls13/session_ticket.c
+++ b/lib/tls13/session_ticket.c
@@ -29,21 +29,31 @@
#include "ext/session_ticket.h"
#include "auth/cert.h"
#include "tls13/session_ticket.h"
+#include "session_pack.h"
static int
-pack_ticket(tls13_ticket_t *ticket, gnutls_datum_t *state)
+pack_ticket(gnutls_session_t session, tls13_ticket_t *ticket, gnutls_datum_t *packed)
{
uint8_t *p;
+ gnutls_datum_t state;
+ int ret;
- state->size = 2 + 4 + 4 +
+ ret = _gnutls_session_pack(session, &state);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ packed->size = 2 + 4 + 4 +
1 + ticket->prf->output_size +
- 1 + ticket->nonce_size;
+ 1 + ticket->nonce_size + 2 + state.size;
- state->data = gnutls_malloc(state->size);
- if (!state->data)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ packed->data = gnutls_malloc(packed->size);
+ if (!packed->data) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
- p = state->data;
+ p = packed->data;
_gnutls_write_uint16(ticket->prf->id, p);
p += 2;
@@ -59,30 +69,41 @@ pack_ticket(tls13_ticket_t *ticket, gnutls_datum_t *state)
p += 1;
memcpy(p, ticket->nonce, ticket->nonce_size);
+ p += ticket->nonce_size;
- return 0;
+ _gnutls_write_uint16(state.size, p);
+ p += 2;
+
+ memcpy(p, state.data, state.size);
+ ret = 0;
+
+ cleanup:
+ gnutls_free(state.data);
+ return ret;
}
static int
-unpack_ticket(gnutls_datum_t *state, tls13_ticket_t *data)
+unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_t *data)
{
uint32_t age_add, lifetime;
uint8_t resumption_master_secret[MAX_HASH_SIZE];
size_t resumption_master_secret_size;
uint8_t nonce[UINT8_MAX];
size_t nonce_size;
+ gnutls_datum_t state;
gnutls_mac_algorithm_t kdf;
const mac_entry_st *prf;
uint8_t *p;
ssize_t len;
+ int ret;
- if (unlikely(state == NULL || data == NULL))
+ if (unlikely(packed == NULL || data == NULL))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
memset(data, 0, sizeof(*data));
- p = state->data;
- len = state->size;
+ p = packed->data;
+ len = packed->size;
DECR_LEN(len, 2);
kdf = _gnutls_read_uint16(p);
@@ -125,6 +146,18 @@ unpack_ticket(gnutls_datum_t *state, tls13_ticket_t *data)
DECR_LEN(len, nonce_size);
memcpy(nonce, p, nonce_size);
+ p += nonce_size;
+
+ DECR_LEN(len, 2);
+ state.size = _gnutls_read_uint16(p);
+ p += 2;
+
+ DECR_LEN(len, state.size);
+ state.data = p;
+
+ ret = _gnutls_session_unpack(session, &state);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
/* No errors - Now return all the data to the caller */
data->prf = prf;
@@ -142,7 +175,7 @@ static int
generate_session_ticket(gnutls_session_t session, tls13_ticket_t *ticket)
{
int ret;
- gnutls_datum_t state = { NULL, 0 };
+ gnutls_datum_t packed = { NULL, 0 };
tls13_ticket_t ticket_data;
/* Generate a random 128-bit ticket nonce */
@@ -170,12 +203,12 @@ generate_session_ticket(gnutls_session_t session, tls13_ticket_t *ticket)
session->key.proto.tls13.ap_rms,
ticket->prf->output_size);
- ret = pack_ticket(&ticket_data, &state);
+ ret = pack_ticket(session, &ticket_data, &packed);
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_encrypt_session_ticket(session, &state, &ticket->ticket);
- _gnutls_free_datum(&state);
+ ret = _gnutls_encrypt_session_ticket(session, &packed, &ticket->ticket);
+ _gnutls_free_datum(&packed);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -343,7 +376,7 @@ int _gnutls13_unpack_session_ticket(gnutls_session_t session,
return gnutls_assert_val(ret);
/* Return ticket parameters */
- ret = unpack_ticket(&decrypted, ticket_data);
+ ret = unpack_ticket(session, &decrypted, ticket_data);
_gnutls_free_datum(&decrypted);
if (ret < 0) {
return ret;