From 0db562fdec5a6dfdd5ec120988b873f1da80aade Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sun, 16 Feb 2025 08:57:08 +0900 Subject: [PATCH 1/3] gnutls_record_set_max_early_data_size: make it callable from client Since commit 9a7ce5a74cbef069394f677c0c79af2c876546db, max_early_data_size is initialized as 0 on the client side, and set only after receiving NewSessionTicket. There are, however, no ways to preserve the max_early_data_size value across multiple calls to gnutls_init. This patch allows the client to set the negotiated max_early_data_size in the second session, through gnutls_record_set_max_early_data_size. Signed-off-by: Daiki Ueno --- lib/ext/early_data.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/ext/early_data.c b/lib/ext/early_data.c index d53b9f4d77..5bcf3a391e 100644 --- a/lib/ext/early_data.c +++ b/lib/ext/early_data.c @@ -124,7 +124,8 @@ size_t gnutls_record_get_max_early_data_size(gnutls_session_t session) * This function sets the maximum early data size in this connection. * This property can only be set to servers. The client may be * provided with the maximum allowed size through the "early_data" - * extension of the NewSessionTicket handshake message. + * extension of the NewSessionTicket handshake message, which can be + * obtained with gnutls_record_get_max_early_data_size(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. @@ -133,11 +134,7 @@ size_t gnutls_record_get_max_early_data_size(gnutls_session_t session) **/ int gnutls_record_set_max_early_data_size(gnutls_session_t session, size_t size) { - if (session->security_parameters.entity == GNUTLS_CLIENT) - return GNUTLS_E_INVALID_REQUEST; - - /* Reject zero as well, as it is useless. */ - if (size == 0 || size > UINT32_MAX) + if (size > UINT32_MAX) return GNUTLS_E_INVALID_REQUEST; session->security_parameters.max_early_data_size = (uint32_t)size; -- 2.48.1 From b8c6d896acc267b3dc00d2ac7c9f8a7f60329d28 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sun, 16 Feb 2025 09:02:46 +0900 Subject: [PATCH 2/3] serv: fix detection of early data reception Upon success, gnutls_record_recv_early_data returns the amount of data received, so the application should treat positive numbers as an indication of early data reception. Signed-off-by: Daiki Ueno --- src/serv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serv.c b/src/serv.c index 17db12c5ca..86008c9523 100644 --- a/src/serv.c +++ b/src/serv.c @@ -1690,7 +1690,7 @@ static void tcp_server(const char *name, int port, int timeout) GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { j->earlydata_eof = 1; } - if (r == 0) { + if (r >= 0) { earlydata_read = 1; } } -- 2.48.1 From 6beabd3aab2990930022c3f77a02b4a5937071d1 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Sun, 16 Feb 2025 09:04:23 +0900 Subject: [PATCH 3/3] cli: preserve negotiated max_early_data_size across resumption Signed-off-by: Daiki Ueno --- src/cli.c | 10 ++++++++-- src/socket.c | 13 +++++++++++-- src/socket.h | 11 +++-------- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/cli.c b/src/cli.c index 4f53b1a02a..5f7199b9f2 100644 --- a/src/cli.c +++ b/src/cli.c @@ -997,6 +997,7 @@ static int try_resume(socket_st *hd) int ret, socket_flags = SOCKET_FLAG_DONT_PRINT_ERRORS; gnutls_datum_t rdata = { NULL, 0 }; gnutls_datum_t edata = { NULL, 0 }; + size_t max_early_data_size = 0; if (gnutls_session_is_resumed(hd->session) == 0) { do { @@ -1010,6 +1011,11 @@ static int try_resume(socket_st *hd) GNUTLS_TLS1_3) || ((gnutls_session_get_flags(hd->session) & GNUTLS_SFLAGS_SESSION_TICKET))) { + max_early_data_size = + gnutls_record_get_max_early_data_size( + hd->session); + log_msg(stdout, "- Max early data size: %zu\n", + max_early_data_size); break; } } while (waitresumption); @@ -1052,7 +1058,7 @@ static int try_resume(socket_st *hd) socket_open_int(hd, hostname, service, OPT_ARG(STARTTLS_PROTO), OPT_ARG(STARTTLS_NAME), socket_flags, CONNECT_MSG, - &rdata, &edata, NULL, NULL); + &rdata, &edata, max_early_data_size, NULL, NULL); log_msg(stdout, "- Resume Handshake was completed\n"); if (gnutls_session_is_resumed(hd->session) != 0) @@ -1365,7 +1371,7 @@ int main(int argc, char **argv) socket_open_int(&hd, hostname, service, OPT_ARG(STARTTLS_PROTO), OPT_ARG(STARTTLS_NAME), socket_flags, CONNECT_MSG, NULL, - NULL, server_fp, client_fp); + NULL, 0, server_fp, client_fp); hd.verbose = verbose; diff --git a/src/socket.c b/src/socket.c index 48784b67fa..1b9d35a589 100644 --- a/src/socket.c +++ b/src/socket.c @@ -461,8 +461,8 @@ inline static int wrap_pull_timeout_func(gnutls_transport_ptr_t ptr, void socket_open_int(socket_st *hd, const char *hostname, const char *service, const char *app_proto, const char *app_hostname, int flags, const char *msg, gnutls_datum_t *rdata, - gnutls_datum_t *edata, FILE *server_trace, - FILE *client_trace) + gnutls_datum_t *edata, size_t max_early_data_size, + FILE *server_trace, FILE *client_trace) { struct addrinfo hints, *res, *ptr; int sd, err = 0; @@ -581,6 +581,15 @@ void socket_open_int(socket_st *hd, const char *hostname, const char *service, if (hd->session) { if (hd->edata.data) { + ret = gnutls_record_set_max_early_data_size( + hd->session, max_early_data_size); + if (ret < 0) { + fprintf(stderr, + "error setting max early data size to %zu\n", + max_early_data_size); + close(sd); + exit(1); + } ret = gnutls_record_send_early_data( hd->session, hd->edata.data, hd->edata.size); diff --git a/src/socket.h b/src/socket.h index 680ca16ade..2696e6f922 100644 --- a/src/socket.h +++ b/src/socket.h @@ -52,17 +52,12 @@ ssize_t socket_send_range(const socket_st *socket, const void *buffer, void socket_open_int(socket_st *hd, const char *hostname, const char *service, const char *app_proto, const char *app_hostname, int flags, const char *msg, gnutls_datum_t *rdata, - gnutls_datum_t *edata, FILE *server_trace, - FILE *client_trace); + gnutls_datum_t *edata, size_t max_early_data_size, + FILE *server_trace, FILE *client_trace); #define socket_open(hd, host, service, app_proto, flags, msg, rdata) \ socket_open_int(hd, host, service, app_proto, NULL, flags, msg, rdata, \ - NULL, NULL, NULL) - -#define socket_open2(hd, host, service, app_proto, flags, msg, rdata, edata, \ - server_trace, client_trace) \ - socket_open_int(hd, host, service, app_proto, NULL, flags, msg, rdata, \ - edata, server_trace, client_trace) + NULL, 0, NULL, NULL) void socket_bye(socket_st *socket, unsigned polite); -- 2.48.1