diff --git a/gnutls-3.8.9-cli-earlydata.patch b/gnutls-3.8.9-cli-earlydata.patch new file mode 100644 index 0000000..b9862fa --- /dev/null +++ b/gnutls-3.8.9-cli-earlydata.patch @@ -0,0 +1,195 @@ +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 + diff --git a/gnutls.spec b/gnutls.spec index bfe2317..a20dd7a 100644 --- a/gnutls.spec +++ b/gnutls.spec @@ -32,6 +32,8 @@ Patch: gnutls-3.8.8-tests-ktls-skip-tls12-chachapoly.patch Patch: gnutls-3.8.9-allow-rsa-pkcs1-encrypt.patch # upstreamed: https://gitlab.com/gnutls/gnutls/-/merge_requests/1930 Patch: gnutls-3.8.9-limit-shuffle-extensions.patch +# not upstreamed: https://gitlab.com/gnutls/gnutls/-/merge_requests/1936 +Patch: gnutls-3.8.9-cli-earlydata.patch %bcond_without bootstrap %bcond_without dane