diff options
-rw-r--r-- | lib/handshake-tls13.c | 10 | ||||
-rw-r--r-- | lib/handshake.c | 14 | ||||
-rw-r--r-- | lib/handshake.h | 5 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/tls13/session_ticket.c | 104 | ||||
-rw-r--r-- | lib/tls13/session_ticket.h | 2 |
6 files changed, 83 insertions, 54 deletions
diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c index 8a8ae52774..631665d7a7 100644 --- a/lib/handshake-tls13.c +++ b/lib/handshake-tls13.c @@ -390,7 +390,7 @@ int _gnutls13_handshake_server(gnutls_session_t session) /* fall through */ case STATE112: - ret = _gnutls13_send_session_ticket(session, AGAIN(STATE112)); + ret = _gnutls13_send_session_ticket(session, 1, AGAIN(STATE112)); STATE = STATE112; IMED_RET("send session ticket", ret, 0); @@ -499,6 +499,7 @@ _gnutls13_recv_async_handshake(gnutls_session_t session, gnutls_buffer_st *buf) /** * gnutls_session_ticket_send: * @session: is a #gnutls_session_t type. + * @nr: the number of tickets to send; must be a positive integer * @flags: must be zero * * Sends a fresh session ticket to the peer. This is relevant only @@ -507,7 +508,7 @@ _gnutls13_recv_async_handshake(gnutls_session_t session, gnutls_buffer_st *buf) * * Returns: %GNUTLS_E_SUCCESS on success, or a negative error code. **/ -int gnutls_session_ticket_send(gnutls_session_t session, unsigned flags) +int gnutls_session_ticket_send(gnutls_session_t session, unsigned nr, unsigned flags) { int ret = 0; const version_entry_st *vers = get_version(session); @@ -515,6 +516,9 @@ int gnutls_session_ticket_send(gnutls_session_t session, unsigned flags) if (!vers->tls13_sem || session->security_parameters.entity == GNUTLS_CLIENT) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + if (nr == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + switch (TICKET_STATE) { case TICKET_STATE0: ret = _gnutls_io_write_flush(session); @@ -526,7 +530,7 @@ int gnutls_session_ticket_send(gnutls_session_t session, unsigned flags) /* fall through */ case TICKET_STATE1: ret = - _gnutls13_send_session_ticket(session, TICKET_STATE==TICKET_STATE1?1:0); + _gnutls13_send_session_ticket(session, nr, TICKET_STATE==TICKET_STATE1?1:0); TICKET_STATE = TICKET_STATE1; if (ret < 0) { gnutls_assert(); diff --git a/lib/handshake.c b/lib/handshake.c index dd2e02908c..5feaed99fd 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -1154,14 +1154,21 @@ int _gnutls_call_hook_func(gnutls_session_t session, (t == GNUTLS_HANDSHAKE_HELLO_REQUEST || t == GNUTLS_HANDSHAKE_KEY_UPDATE || \ (t == GNUTLS_HANDSHAKE_NEW_SESSION_TICKET && v->tls13_sem)) +int +_gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel, + gnutls_handshake_description_t type) +{ + return _gnutls_send_handshake2(session, bufel, type, 0); +} + /* This function sends a handshake message of type 'type' containing the * data specified here. If the previous _gnutls_send_handshake() returned * GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED, then it must be called again * (until it returns ok), with NULL parameters. */ int -_gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel, - gnutls_handshake_description_t type) +_gnutls_send_handshake2(gnutls_session_t session, mbuffer_st * bufel, + gnutls_handshake_description_t type, unsigned queue_only) { int ret; uint8_t *data; @@ -1244,6 +1251,9 @@ _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel, return ret; } + if (queue_only) + return 0; + /* Decide when to cache and when to send */ if (vers && vers->tls13_sem) { diff --git a/lib/handshake.h b/lib/handshake.h index 465ee03b80..390f5034f9 100644 --- a/lib/handshake.h +++ b/lib/handshake.h @@ -61,6 +61,11 @@ int _gnutls_recv_hello_request(gnutls_session_t session, void *data, int _gnutls_recv_handshake(gnutls_session_t session, gnutls_handshake_description_t type, unsigned int optional, gnutls_buffer_st * buf); + +int +_gnutls_send_handshake2(gnutls_session_t session, mbuffer_st * bufel, + gnutls_handshake_description_t type, unsigned queue_only); + int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len); int _gnutls_gen_server_random(gnutls_session_t session, int version); void _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd); diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index b675035f3e..f57d0d7cc7 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1480,7 +1480,7 @@ int gnutls_session_ticket_enable_client(gnutls_session_t session); int gnutls_session_ticket_enable_server(gnutls_session_t session, const gnutls_datum_t * key); -int gnutls_session_ticket_send(gnutls_session_t session, unsigned flags); +int gnutls_session_ticket_send(gnutls_session_t session, unsigned nr, unsigned flags); /* SRTP, RFC 5764 */ diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c index 77edbcda91..184c0ac271 100644 --- a/lib/tls13/session_ticket.c +++ b/lib/tls13/session_ticket.c @@ -227,12 +227,13 @@ generate_session_ticket(gnutls_session_t session, tls13_ticket_t *ticket) return 0; } -int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned again) +int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again) { int ret = 0; mbuffer_st *bufel = NULL; gnutls_buffer_st buf; tls13_ticket_t ticket; + unsigned i; /* Client does not send a NewSessionTicket */ if (unlikely(session->security_parameters.entity == GNUTLS_CLIENT)) @@ -249,70 +250,79 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned again) return gnutls_assert_val(0); if (again == 0) { - memset(&ticket, 0, sizeof(tls13_ticket_t)); - - ret = generate_session_ticket(session, &ticket); - if (ret < 0) { - if (ret == GNUTLS_E_INT_RET_0) { - return gnutls_assert_val(0); + for (i=0;i<nr;i++) { + memset(&ticket, 0, sizeof(tls13_ticket_t)); + bufel = NULL; + + ret = _gnutls_buffer_init_handshake_mbuffer(&buf); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = generate_session_ticket(session, &ticket); + if (ret < 0) { + if (ret == GNUTLS_E_INT_RET_0) { + ret = gnutls_assert_val(0); + goto cleanup; + } + gnutls_assert(); + goto cleanup; } - return gnutls_assert_val(ret); - } + ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.lifetime); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - ret = _gnutls_buffer_init_handshake_mbuffer(&buf); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.age_add); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.lifetime); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + /* append ticket_nonce */ + ret = _gnutls_buffer_append_data_prefix(&buf, 8, ticket.nonce, ticket.nonce_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.age_add); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + /* append ticket */ + ret = _gnutls_buffer_append_data_prefix(&buf, 16, ticket.ticket.data, ticket.ticket.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - /* append ticket_nonce */ - ret = _gnutls_buffer_append_data_prefix(&buf, 8, ticket.nonce, ticket.nonce_size); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + ret = _gnutls_buffer_append_prefix(&buf, 16, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - /* append ticket */ - ret = _gnutls_buffer_append_data_prefix(&buf, 16, ticket.ticket.data, ticket.ticket.size); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + _gnutls_free_datum(&ticket.ticket); - ret = _gnutls_buffer_append_prefix(&buf, 16, 0); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + bufel = _gnutls_buffer_to_mbuffer(&buf); - _gnutls_free_datum(&ticket.ticket); + ret = _gnutls_send_handshake2(session, bufel, + GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - bufel = _gnutls_buffer_to_mbuffer(&buf); + session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT; + } } - ret = _gnutls_send_handshake(session, bufel, - GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); - if (ret > 0) - session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT; + ret = _gnutls_handshake_io_write_flush(session); return ret; cleanup: _gnutls_free_datum(&ticket.ticket); _mbuffer_xfree(&bufel); + _gnutls_buffer_clear(&buf); return ret; } diff --git a/lib/tls13/session_ticket.h b/lib/tls13/session_ticket.h index 073c28f1f2..d2f637c209 100644 --- a/lib/tls13/session_ticket.h +++ b/lib/tls13/session_ticket.h @@ -23,7 +23,7 @@ #define SESSION_TICKET_H int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf); -int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned again); +int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again); int _gnutls13_unpack_session_ticket(gnutls_session_t session, gnutls_datum_t *data, |