diff options
Diffstat (limited to 'lib/session_pack.c')
-rw-r--r-- | lib/session_pack.c | 388 |
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 - |