summaryrefslogtreecommitdiff
path: root/lib/session_pack.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/session_pack.c')
-rw-r--r--lib/session_pack.c388
1 files changed, 262 insertions, 126 deletions
diff --git a/lib/session_pack.c b/lib/session_pack.c
index 977110595b..615eb6c2a5 100644
--- a/lib/session_pack.c
+++ b/lib/session_pack.c
@@ -44,6 +44,7 @@
#include <algorithms.h>
#include <state.h>
#include <db.h>
+#include "tls13/session_ticket.h"
static int pack_certificate_auth_info(gnutls_session_t,
gnutls_buffer_st * packed_session);
@@ -69,6 +70,10 @@ static int unpack_security_parameters(gnutls_session_t session,
gnutls_buffer_st * packed_session);
static int pack_security_parameters(gnutls_session_t session,
gnutls_buffer_st * packed_session);
+static int tls13_unpack_security_parameters(gnutls_session_t session,
+ gnutls_buffer_st * packed_session);
+static int tls13_pack_security_parameters(gnutls_session_t session,
+ gnutls_buffer_st * packed_session);
/* Since auth_info structures contain malloced data, this function
@@ -150,10 +155,22 @@ _gnutls_session_pack(gnutls_session_t session,
goto fail;
}
- ret = _gnutls_hello_ext_pack(session, &sb);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
+
+ if (session->security_parameters.pversion->tls13_sem) {
+ ret = tls13_pack_security_parameters(session, &sb);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
+ }
+
+ /* Extensions are re-negotiated in a resumed session under TLS 1.3 */
+ if (!session->security_parameters.pversion->tls13_sem) {
+ ret = _gnutls_hello_ext_pack(session, &sb);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
+ }
}
return _gnutls_buffer_to_datum(&sb, packed_session, 0);
@@ -256,10 +273,21 @@ _gnutls_session_unpack(gnutls_session_t session,
goto error;
}
- ret = _gnutls_hello_ext_unpack(session, &sb);
- if (ret < 0) {
- gnutls_assert();
- goto error;
+ if (session->internals.resumed_security_parameters.pversion->tls13_sem) {
+ /* 'prf' will not be NULL at this point, else unpack_security_parameters() would have failed */
+ ret = tls13_unpack_security_parameters(session, &sb);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ }
+
+ if (!session->internals.resumed_security_parameters.pversion->tls13_sem) {
+ ret = _gnutls_hello_ext_unpack(session, &sb);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
}
ret = 0;
@@ -270,7 +298,107 @@ _gnutls_session_unpack(gnutls_session_t session,
return ret;
}
+/*
+ * If we're using TLS 1.3 semantics, we might have TLS 1.3-specific data.
+ * Format:
+ * 4 bytes the total length
+ * 4 bytes the ticket lifetime
+ * 4 bytes the ticket age add value
+ * 1 byte the ticket nonce length
+ * x bytes the ticket nonce
+ * 4 bytes the ticket length
+ * x bytes the ticket
+ * 1 bytes the resumption master secret length
+ * x bytes the resumption master secret
+ *
+ * WE DON'T STORE NewSessionTicket EXTENSIONS, as we don't support them yet.
+ *
+ * We only store that info if we received a TLS 1.3 NewSessionTicket at some point.
+ * If we didn't receive any NST then we cannot resume a TLS 1.3 session and hence
+ * its nonsense to store all that info.
+ */
+static int
+tls13_pack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps)
+{
+ int ret = 0;
+ uint32_t length = 0;
+ size_t length_pos;
+ tls13_ticket_t *ticket = &session->internals.tls13_ticket;
+
+ length_pos = ps->length;
+ BUFFER_APPEND_NUM(ps, 0);
+ if (ticket->ticket.data != NULL) {
+ BUFFER_APPEND_NUM(ps, ticket->timestamp);
+ length += 4;
+ BUFFER_APPEND_NUM(ps, ticket->lifetime);
+ length += 4;
+ BUFFER_APPEND_NUM(ps, ticket->age_add);
+ length += 4;
+ BUFFER_APPEND_PFX1(ps,
+ ticket->nonce,
+ ticket->nonce_size);
+ length += (1 + ticket->nonce_size);
+ BUFFER_APPEND_PFX4(ps,
+ ticket->ticket.data,
+ ticket->ticket.size);
+ length += (4 + ticket->ticket.size);
+ BUFFER_APPEND_PFX1(ps,
+ ticket->resumption_master_secret,
+ ticket->prf->output_size);
+ length += (1 + ticket->prf->output_size);
+
+ /* Overwrite the length field */
+ _gnutls_write_uint32(length, ps->data + length_pos);
+ }
+
+ return ret;
+}
+
+static int
+tls13_unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps)
+{
+ uint32_t ttl_len;
+ tls13_ticket_t *ticket = &session->internals.tls13_ticket;
+ gnutls_datum_t t;
+ int ret = 0;
+
+ BUFFER_POP_NUM(ps, ttl_len);
+
+ if (ttl_len > 0) {
+ BUFFER_POP_NUM(ps, ticket->timestamp);
+ BUFFER_POP_NUM(ps, ticket->lifetime);
+ BUFFER_POP_NUM(ps, ticket->age_add);
+
+ ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
+ if (ret < 0 || t.size > sizeof(ticket->nonce)) {
+ ret = GNUTLS_E_PARSING_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ ticket->nonce_size = t.size;
+ memcpy(ticket->nonce, t.data, t.size);
+
+ BUFFER_POP_DATUM(ps, &ticket->ticket);
+
+ ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
+ if (ret < 0 || t.size > sizeof(ticket->resumption_master_secret)) {
+ ret = GNUTLS_E_PARSING_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ memcpy(ticket->resumption_master_secret, t.data, t.size);
+
+ if (unlikely(session->internals.resumed_security_parameters.prf == NULL ||
+ session->internals.resumed_security_parameters.prf->output_size != t.size))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ ticket->prf = session->internals.resumed_security_parameters.prf;
+ }
+
+error:
+ return ret;
+}
/* Format:
* 1 byte the credentials type
@@ -723,37 +851,6 @@ unpack_psk_auth_info(gnutls_session_t session, gnutls_buffer_st * ps)
/* Packs the security parameters.
*/
-
-/* Format:
- * 4 bytes the total security data size
- * 1 byte the entity type (client/server)
- * 1 byte the key exchange algorithm used
- * 1 byte the read cipher algorithm
- * 1 byte the read mac algorithm
- *
- * 1 byte the write cipher algorithm
- * 1 byte the write mac algorithm
- *
- * 1 byte the certificate type
- * 1 byte the protocol version
- *
- * 2 bytes the cipher suite
- * 4 bytes the PRF ID
- *
- * 48 bytes the master secret
- *
- * 32 bytes the client random
- * 32 bytes the server random
- *
- * 1 byte the session ID size
- * x bytes the session ID (32 bytes max)
- *
- * 4 bytes the new record padding flag
- * 4 bytes the ECC curve
- * -------------------
- * MAX: 169 bytes
- *
- */
static int
pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
{
@@ -780,49 +877,58 @@ pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
BUFFER_APPEND_NUM(ps, 0);
cur_size = ps->length;
-
BUFFER_APPEND_NUM(ps, session->security_parameters.entity);
- BUFFER_APPEND(ps, session->security_parameters.cs->id, 2);
BUFFER_APPEND_NUM(ps, session->security_parameters.prf->id);
- BUFFER_APPEND_NUM(ps, session->security_parameters.cert_type);
- BUFFER_APPEND_NUM(ps, session->security_parameters.pversion->id);
-
- BUFFER_APPEND(ps, session->security_parameters.master_secret,
- GNUTLS_MASTER_SIZE);
- BUFFER_APPEND(ps, session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
- BUFFER_APPEND(ps, session->security_parameters.server_random,
- GNUTLS_RANDOM_SIZE);
-
- BUFFER_APPEND(ps, &session->security_parameters.session_id_size,
- 1);
- BUFFER_APPEND(ps, session->security_parameters.session_id,
- session->security_parameters.session_id_size);
-
BUFFER_APPEND_NUM(ps,
- session->security_parameters.
- max_record_send_size);
+ session->security_parameters.client_auth_type);
BUFFER_APPEND_NUM(ps,
- session->security_parameters.
- max_record_recv_size);
+ session->security_parameters.server_auth_type);
- if (session->security_parameters.grp) {
- BUFFER_APPEND_NUM(ps, session->security_parameters.grp->id);
- } else {
- BUFFER_APPEND_NUM(ps, 0);
- }
+ BUFFER_APPEND_NUM(ps, session->security_parameters.pversion->id);
- BUFFER_APPEND_NUM(ps, session->security_parameters.post_handshake_auth);
+ /* if we are under TLS 1.3 do not pack keys or params negotiated using an extension
+ * they are not necessary */
+ if (!session->security_parameters.pversion->tls13_sem) {
+ BUFFER_APPEND(ps, session->security_parameters.cs->id, 2);
+
+ BUFFER_APPEND_NUM(ps, session->security_parameters.cert_type);
+
+ BUFFER_APPEND_PFX1(ps, session->security_parameters.master_secret,
+ GNUTLS_MASTER_SIZE);
+ BUFFER_APPEND_PFX1(ps, session->security_parameters.client_random,
+ GNUTLS_RANDOM_SIZE);
+ BUFFER_APPEND_PFX1(ps, session->security_parameters.server_random,
+ GNUTLS_RANDOM_SIZE);
+
+ BUFFER_APPEND(ps, &session->security_parameters.session_id_size,
+ 1);
+ BUFFER_APPEND(ps, session->security_parameters.session_id,
+ session->security_parameters.session_id_size);
+
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.
+ max_record_send_size);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.
+ max_record_recv_size);
+
+ if (session->security_parameters.grp) {
+ BUFFER_APPEND_NUM(ps, session->security_parameters.grp->id);
+ } else {
+ BUFFER_APPEND_NUM(ps, 0);
+ }
+
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.server_sign_algo);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.client_sign_algo);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.ext_master_secret);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.etm);
+ }
- BUFFER_APPEND_NUM(ps,
- session->security_parameters.server_sign_algo);
- BUFFER_APPEND_NUM(ps,
- session->security_parameters.client_sign_algo);
- BUFFER_APPEND_NUM(ps,
- session->security_parameters.ext_master_secret);
- BUFFER_APPEND_NUM(ps,
- session->security_parameters.etm);
_gnutls_write_uint32(ps->length - cur_size,
ps->data + size_offset);
@@ -836,6 +942,7 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
size_t pack_size;
int ret;
unsigned version;
+ gnutls_datum_t t;
time_t timestamp;
uint8_t cs[2];
@@ -856,10 +963,6 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
BUFFER_POP_NUM(ps,
session->internals.resumed_security_parameters.
entity);
- BUFFER_POP(ps, cs, 2);
- session->internals.resumed_security_parameters.cs = ciphersuite_to_entry(cs);
- if (session->internals.resumed_security_parameters.cs == NULL)
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
BUFFER_POP_NUM(ps, version);
session->internals.resumed_security_parameters.prf = mac_to_entry(version);
@@ -868,7 +971,11 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
BUFFER_POP_NUM(ps,
session->internals.resumed_security_parameters.
- cert_type);
+ client_auth_type);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ server_auth_type);
+
BUFFER_POP_NUM(ps, version);
session->internals.resumed_security_parameters.pversion =
version_to_entry(version);
@@ -876,57 +983,86 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
NULL)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- BUFFER_POP(ps,
- session->internals.resumed_security_parameters.
- master_secret, GNUTLS_MASTER_SIZE);
-
- BUFFER_POP(ps,
- session->internals.resumed_security_parameters.
- client_random, GNUTLS_RANDOM_SIZE);
- BUFFER_POP(ps,
- session->internals.resumed_security_parameters.
- server_random, GNUTLS_RANDOM_SIZE);
- BUFFER_POP(ps,
- &session->internals.resumed_security_parameters.
- session_id_size, 1);
-
- BUFFER_POP(ps,
- session->internals.resumed_security_parameters.
- session_id,
- session->internals.resumed_security_parameters.
- session_id_size);
+ if (!session->internals.resumed_security_parameters.pversion->tls13_sem) {
+ BUFFER_POP(ps, cs, 2);
+ session->internals.resumed_security_parameters.cs = ciphersuite_to_entry(cs);
+ if (session->internals.resumed_security_parameters.cs == NULL)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- max_record_send_size);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- max_record_recv_size);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ cert_type);
- BUFFER_POP_NUM(ps, ret);
- session->internals.resumed_security_parameters.grp = _gnutls_id_to_group(ret);
- /* it can be null */
-
- BUFFER_POP_NUM(ps, session->security_parameters.post_handshake_auth);
+ /* master secret */
+ ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
+ if (ret < 0) {
+ ret = GNUTLS_E_PARSING_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ if (t.size == GNUTLS_MASTER_SIZE)
+ memcpy(session->internals.resumed_security_parameters.master_secret, t.data, t.size);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- server_sign_algo);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- client_sign_algo);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- ext_master_secret);
- BUFFER_POP_NUM(ps,
- session->internals.resumed_security_parameters.
- etm);
+ /* client random */
+ ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
+ if (ret < 0) {
+ ret = GNUTLS_E_PARSING_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ if (t.size == GNUTLS_RANDOM_SIZE)
+ memcpy(session->internals.resumed_security_parameters.client_random, t.data, t.size);
- if (session->internals.resumed_security_parameters.
- max_record_recv_size == 0
- || session->internals.resumed_security_parameters.
- max_record_send_size == 0) {
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ /* server random */
+ ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
+ if (ret < 0) {
+ ret = GNUTLS_E_PARSING_ERROR;
+ gnutls_assert();
+ goto error;
+ }
+ if (t.size == GNUTLS_RANDOM_SIZE)
+ memcpy(session->internals.resumed_security_parameters.server_random, t.data, t.size);
+
+ BUFFER_POP(ps,
+ &session->internals.resumed_security_parameters.
+ session_id_size, 1);
+
+ BUFFER_POP(ps,
+ session->internals.resumed_security_parameters.
+ session_id,
+ session->internals.resumed_security_parameters.
+ session_id_size);
+
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ max_record_send_size);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ max_record_recv_size);
+
+ BUFFER_POP_NUM(ps, ret);
+ session->internals.resumed_security_parameters.grp = _gnutls_id_to_group(ret);
+ /* it can be null */
+
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ server_sign_algo);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ client_sign_algo);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ ext_master_secret);
+ BUFFER_POP_NUM(ps,
+ session->internals.resumed_security_parameters.
+ etm);
+
+ if (session->internals.resumed_security_parameters.
+ max_record_recv_size == 0
+ || session->internals.resumed_security_parameters.
+ max_record_send_size == 0) {
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ }
}
if (timestamp -