diff -Nru gnutls28-3.7.1/debian/changelog gnutls28-3.7.1/debian/changelog --- gnutls28-3.7.1/debian/changelog 2021-04-14 09:44:37.000000000 -0500 +++ gnutls28-3.7.1/debian/changelog 2021-05-21 10:31:30.000000000 -0500 @@ -1,3 +1,38 @@ +gnutls28 (3.7.1-4ubuntu1) impish; urgency=low + + * Merge from Debian unstable. Remaining changes: + - Enable CET. + - Set default priority string to only allow TLS1.2, DTLS1.2, and + TLS1.3 with medium security profile (2048 RSA keys minimum, and + similar). + * Fix FTBFS with lto - reduce parallelism to 2. LP: #1922004 + * Merge CVE fixes CVE-2021-20231 CVE-2021-20232 + + -- William 'jawn-smith' Wilson Fri, 21 May 2021 10:29:32 -0600 + +gnutls28 (3.7.1-4) unstable; urgency=medium + + * Pull fixes from upstream Git master + + Ensure array allocations overflow safe. + https://gitlab.com/gnutls/gnutls/-/issues/1179 + 56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch + 56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch + 56_17-build-avoid-potential-integer-overflow-in-array-allo.patch + 56_18-build-avoid-integer-overflow-in-additions.patch + 56_19-_gnutls_calloc-remove-unused-function.patch + + Add option to disable TLS 1.3 middlebox compatibility mode + https://gitlab.com/gnutls/gnutls/-/issues/1208 + 56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch + (Changes gperf input file, add b-d on gperf.) + + Fix session-id changing when responding to HelloRetryRequest + 56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch + https://gitlab.com/gnutls/gnutls/-/issues/1210 + + Fix timing of sending TLSv1.3 early data. + 56_28-handshake-fix-timing-of-sending-early-data.patch + https://gitlab.com/gnutls/gnutls/-/issues/1146 + + -- Andreas Metzler Sun, 25 Apr 2021 12:55:14 +0200 + gnutls28 (3.7.1-3ubuntu1) hirsute; urgency=medium * Merge from Debian unstable. Remaining changes: diff -Nru gnutls28-3.7.1/debian/control gnutls28-3.7.1/debian/control --- gnutls28-3.7.1/debian/control 2021-04-14 09:24:04.000000000 -0500 +++ gnutls28-3.7.1/debian/control 2021-04-25 10:13:26.000000000 -0500 @@ -16,6 +16,7 @@ datefudge , debhelper-compat (=13), freebsd-net-tools [kfreebsd-i386 kfreebsd-amd64] , + gperf, guile-2.2-dev , libcmocka-dev , libgmp-dev (>= 2:6), diff -Nru gnutls28-3.7.1/debian/patches/56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch gnutls28-3.7.1/debian/patches/56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch --- gnutls28-3.7.1/debian/patches/56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch 2021-04-24 09:57:17.000000000 -0500 @@ -0,0 +1,88 @@ +From 94d2192a37efc9b94f59fb0ba474a7be8b6895d4 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sun, 21 Feb 2021 08:42:23 +0100 +Subject: [PATCH 1/5] mem: add _gnutls_reallocarray and + _gnutls_reallocarray_fast + +Signed-off-by: Daiki Ueno +--- + lib/mem.c | 24 ++++++++++++++++++++++++ + lib/mem.h | 7 +++++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/lib/mem.c b/lib/mem.c +index 32cab5a47c..9a74456dbb 100644 +--- a/lib/mem.c ++++ b/lib/mem.c +@@ -24,6 +24,7 @@ + #include "errors.h" + #include + #include ++#include "xalloc-oversized.h" + + gnutls_alloc_function gnutls_secure_malloc = malloc; + gnutls_alloc_function gnutls_malloc = malloc; +@@ -61,6 +62,23 @@ void *gnutls_realloc_fast(void *ptr, size_t size) + return ret; + } + ++/* This will free ptr in case reallocarray fails. ++ */ ++void *_gnutls_reallocarray_fast(void *ptr, size_t nmemb, size_t size) ++{ ++ void *ret; ++ ++ if (size == 0) ++ return ptr; ++ ++ ret = _gnutls_reallocarray(ptr, nmemb, size); ++ if (ret == NULL) { ++ gnutls_free(ptr); ++ } ++ ++ return ret; ++} ++ + char *_gnutls_strdup(const char *str) + { + size_t siz; +@@ -77,6 +95,12 @@ char *_gnutls_strdup(const char *str) + return ret; + } + ++void *_gnutls_reallocarray(void *ptr, size_t nmemb, size_t size) ++{ ++ return xalloc_oversized(nmemb, size) ? NULL : ++ gnutls_realloc(ptr, nmemb * size); ++} ++ + #if 0 + /* don't use them. They are included for documentation. + */ +diff --git a/lib/mem.h b/lib/mem.h +index d3eea97a40..13f47f17b4 100644 +--- a/lib/mem.h ++++ b/lib/mem.h +@@ -25,14 +25,17 @@ + + #include + +-/* this realloc function will return ptr if size==0, and +- * will free the ptr if the new allocation failed. ++/* These realloc functions will return ptr if size==0, and will free ++ * the ptr if the new allocation failed. + */ + void *gnutls_realloc_fast(void *ptr, size_t size); ++void *_gnutls_reallocarray_fast(void *ptr, size_t nmemb, size_t size); + + void *_gnutls_calloc(size_t nmemb, size_t size); + char *_gnutls_strdup(const char *); + ++void *_gnutls_reallocarray(void *, size_t, size_t); ++ + unsigned _gnutls_mem_is_zero(const uint8_t *ptr, unsigned size); + + #define zrelease_mpi_key(mpi) if (*mpi!=NULL) { \ +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch gnutls28-3.7.1/debian/patches/56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch --- gnutls28-3.7.1/debian/patches/56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch 2021-04-24 09:57:17.000000000 -0500 @@ -0,0 +1,29 @@ +From 93a86b1ecae876bd76c6c1d7b73d8588f753b963 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 29 Mar 2021 13:08:23 +0200 +Subject: [PATCH 2/5] pkcs11x: find_ext_cb: fix error propagation + +Use explicit error value, as rv is not set in this code path. + +Signed-off-by: Daiki Ueno +--- + lib/pkcs11x.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/lib/pkcs11x.c b/lib/pkcs11x.c +index 0041b924cb..ee0b431685 100644 +--- a/lib/pkcs11x.c ++++ b/lib/pkcs11x.c +@@ -219,8 +219,7 @@ find_ext_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, + + find_data->exts = gnutls_realloc_fast(find_data->exts, (1+find_data->exts_size)*sizeof(find_data->exts[0])); + if (find_data->exts == NULL) { +- gnutls_assert(); +- ret = pkcs11_rv_to_err(rv); ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; + } + +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_17-build-avoid-potential-integer-overflow-in-array-allo.patch gnutls28-3.7.1/debian/patches/56_17-build-avoid-potential-integer-overflow-in-array-allo.patch --- gnutls28-3.7.1/debian/patches/56_17-build-avoid-potential-integer-overflow-in-array-allo.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_17-build-avoid-potential-integer-overflow-in-array-allo.patch 2021-04-24 09:57:17.000000000 -0500 @@ -0,0 +1,531 @@ +From 584783a3fc2048ca6673ccdc4f44d0ffc46080cb Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sun, 21 Feb 2021 08:43:26 +0100 +Subject: [PATCH 3/5] build: avoid potential integer overflow in array + allocation + +This relies on _gnutls_reallocarray for all occasions of array +allocations, so that they can benefit from the built-in overflow +checks. + +Signed-off-by: Daiki Ueno +--- + lib/cert-cred-x509.c | 23 ++++++++++++++-------- + lib/cert-cred.c | 18 +++++++++-------- + lib/hello_ext.c | 4 +++- + lib/pcert.c | 3 ++- + lib/pkcs11.c | 11 +++++++---- + lib/pkcs11x.c | 5 ++++- + lib/supplemental.c | 4 ++-- + lib/x509/crl.c | 7 +++---- + lib/x509/ocsp.c | 11 ++++++----- + lib/x509/pkcs12.c | 15 ++++++-------- + lib/x509/verify-high.c | 43 +++++++++++++++++------------------------ + lib/x509/verify-high2.c | 6 ++++-- + lib/x509/x509.c | 9 ++++----- + lib/x509/x509_ext.c | 12 ++++++------ + 14 files changed, 90 insertions(+), 81 deletions(-) + +diff --git a/lib/cert-cred-x509.c b/lib/cert-cred-x509.c +index 1b44f3a634..543a1155f4 100644 +--- a/lib/cert-cred-x509.c ++++ b/lib/cert-cred-x509.c +@@ -254,7 +254,7 @@ parse_pem_cert_mem(gnutls_certificate_credentials_t res, + goto cleanup; + } + +- pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count); ++ pcerts = _gnutls_reallocarray(NULL, count, sizeof(gnutls_pcert_st)); + if (pcerts == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -441,7 +441,8 @@ read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const + + _gnutls_str_array_init(&names); + +- ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN); ++ ccert = _gnutls_reallocarray(NULL, MAX_PKCS11_CERT_CHAIN, ++ sizeof(*ccert)); + if (ccert == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; +@@ -770,7 +771,8 @@ gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res, + } + + /* load certificates */ +- pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size); ++ pcerts = _gnutls_reallocarray(NULL, cert_list_size, ++ sizeof(gnutls_pcert_st)); + if (pcerts == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -901,8 +903,9 @@ gnutls_certificate_get_x509_crt(gnutls_certificate_credentials_t res, + } + + *crt_list_size = res->certs[index].cert_list_length; +- *crt_list = gnutls_malloc( +- res->certs[index].cert_list_length * sizeof (gnutls_x509_crt_t)); ++ *crt_list = _gnutls_reallocarray(NULL, ++ res->certs[index].cert_list_length, ++ sizeof (gnutls_x509_crt_t)); + if (*crt_list == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -1151,7 +1154,8 @@ gnutls_certificate_set_x509_trust(gnutls_certificate_credentials_t res, + if (ca_list == NULL || ca_list_size < 1) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + +- new_list = gnutls_malloc(ca_list_size * sizeof(gnutls_x509_crt_t)); ++ new_list = _gnutls_reallocarray(NULL, ca_list_size, ++ sizeof(gnutls_x509_crt_t)); + if (!new_list) + return GNUTLS_E_MEMORY_ERROR; + +@@ -1335,12 +1339,15 @@ gnutls_certificate_set_x509_crl(gnutls_certificate_credentials_t res, + int crl_list_size) + { + int ret, i, j; +- gnutls_x509_crl_t *new_crl = gnutls_malloc(crl_list_size * sizeof(gnutls_x509_crl_t)); +- unsigned flags = GNUTLS_TL_USE_IN_TLS; ++ gnutls_x509_crl_t *new_crl; ++ unsigned flags; + ++ flags = GNUTLS_TL_USE_IN_TLS; + if (res->flags & GNUTLS_CERTIFICATE_VERIFY_CRLS) + flags |= GNUTLS_TL_VERIFY_CRL|GNUTLS_TL_FAIL_ON_INVALID_CRL; + ++ new_crl = _gnutls_reallocarray(NULL, crl_list_size, ++ sizeof(gnutls_x509_crl_t)); + if (!new_crl) + return GNUTLS_E_MEMORY_ERROR; + +diff --git a/lib/cert-cred.c b/lib/cert-cred.c +index 28b67f60df..3f1041f73b 100644 +--- a/lib/cert-cred.c ++++ b/lib/cert-cred.c +@@ -55,15 +55,15 @@ _gnutls_certificate_credential_append_keypair(gnutls_certificate_credentials_t r + gnutls_pcert_st * crt, + int nr) + { +- res->sorted_cert_idx = gnutls_realloc_fast(res->sorted_cert_idx, +- (1 + res->ncerts) * +- sizeof(unsigned int)); ++ res->sorted_cert_idx = _gnutls_reallocarray_fast(res->sorted_cert_idx, ++ res->ncerts + 1, ++ sizeof(unsigned int)); + if (res->sorted_cert_idx == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + +- res->certs = gnutls_realloc_fast(res->certs, +- (1 + res->ncerts) * +- sizeof(certs_st)); ++ res->certs = _gnutls_reallocarray_fast(res->certs, ++ res->ncerts + 1, ++ sizeof(certs_st)); + if (res->certs == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + +@@ -204,7 +204,8 @@ gnutls_certificate_set_key(gnutls_certificate_credentials_t res, + gnutls_privkey_set_pin_function(key, res->pin.cb, + res->pin.data); + +- new_pcert_list = gnutls_malloc(sizeof(gnutls_pcert_st) * pcert_list_size); ++ new_pcert_list = _gnutls_reallocarray(NULL, pcert_list_size, ++ sizeof(gnutls_pcert_st)); + if (new_pcert_list == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +@@ -451,7 +452,8 @@ static gnutls_pcert_st *alloc_and_load_x509_certs(gnutls_x509_crt_t * + if (certs == NULL) + return NULL; + +- local_certs = gnutls_malloc(sizeof(gnutls_pcert_st) * ncerts); ++ local_certs = _gnutls_reallocarray(NULL, ncerts, ++ sizeof(gnutls_pcert_st)); + if (local_certs == NULL) { + gnutls_assert(); + return NULL; +diff --git a/lib/hello_ext.c b/lib/hello_ext.c +index dbe73fdeb3..6943d095b3 100644 +--- a/lib/hello_ext.c ++++ b/lib/hello_ext.c +@@ -923,7 +923,9 @@ gnutls_session_ext_register(gnutls_session_t session, + tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS; + } + +- exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts)); ++ exts = _gnutls_reallocarray(session->internals.rexts, ++ session->internals.rexts_size + 1, ++ sizeof(*exts)); + if (exts == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +diff --git a/lib/pcert.c b/lib/pcert.c +index 89d3d40e63..e5057aec51 100644 +--- a/lib/pcert.c ++++ b/lib/pcert.c +@@ -185,7 +185,8 @@ gnutls_pcert_list_import_x509_raw(gnutls_pcert_st *pcert_list, + unsigned int i = 0, j; + gnutls_x509_crt_t *crt; + +- crt = gnutls_malloc((*pcert_list_size) * sizeof(gnutls_x509_crt_t)); ++ crt = _gnutls_reallocarray(NULL, *pcert_list_size, ++ sizeof(gnutls_x509_crt_t)); + + if (crt == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); +diff --git a/lib/pkcs11.c b/lib/pkcs11.c +index 0d5e83a0c6..7e8c0570ac 100644 +--- a/lib/pkcs11.c ++++ b/lib/pkcs11.c +@@ -3059,8 +3059,8 @@ find_privkeys(struct pkcs11_session_info *sinfo, + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + +- list->key_ids = +- gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size); ++ list->key_ids = _gnutls_reallocarray(NULL, list->key_ids_size, ++ sizeof(gnutls_buffer_st)); + if (list->key_ids == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -3277,7 +3277,7 @@ find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info * + return pkcs11_rv_to_err(rv); + } + +- ctx = gnutls_malloc(OBJECTS_A_TIME*sizeof(ctx[0])); ++ ctx = _gnutls_reallocarray(NULL, OBJECTS_A_TIME, sizeof(ctx[0])); + if (ctx == NULL) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto fail; +@@ -3291,7 +3291,10 @@ find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info * + unsigned j; + gnutls_datum_t id; + +- find_data->p_list = gnutls_realloc_fast(find_data->p_list, (find_data->current+count)*sizeof(find_data->p_list[0])); ++ find_data->p_list = ++ _gnutls_reallocarray_fast(find_data->p_list, ++ find_data->current + count, ++ sizeof(find_data->p_list[0])); + if (find_data->p_list == NULL) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto fail; +diff --git a/lib/pkcs11x.c b/lib/pkcs11x.c +index ee0b431685..7bb62f64bf 100644 +--- a/lib/pkcs11x.c ++++ b/lib/pkcs11x.c +@@ -217,7 +217,10 @@ find_ext_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, + rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &ext); + if (rv == CKR_OK) { + +- find_data->exts = gnutls_realloc_fast(find_data->exts, (1+find_data->exts_size)*sizeof(find_data->exts[0])); ++ find_data->exts = ++ _gnutls_reallocarray_fast(find_data->exts, ++ find_data->exts_size + 1, ++ sizeof(find_data->exts[0])); + if (find_data->exts == NULL) { + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto cleanup; +diff --git a/lib/supplemental.c b/lib/supplemental.c +index 07b38cc938..fc9545526a 100644 +--- a/lib/supplemental.c ++++ b/lib/supplemental.c +@@ -252,8 +252,8 @@ _gnutls_supplemental_register(gnutls_supplemental_entry_st *entry) + return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED); + } + +- p = gnutls_realloc_fast(suppfunc, +- sizeof(*suppfunc) * (suppfunc_size + 1)); ++ p = _gnutls_reallocarray_fast(suppfunc, suppfunc_size + 1, ++ sizeof(*suppfunc)); + if (!p) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +diff --git a/lib/x509/crl.c b/lib/x509/crl.c +index 8705be3b6c..aea8bc6d33 100644 +--- a/lib/x509/crl.c ++++ b/lib/x509/crl.c +@@ -1262,7 +1262,7 @@ gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls, + unsigned int init = 1024; + int ret; + +- *crls = gnutls_malloc(sizeof(gnutls_x509_crl_t) * init); ++ *crls = _gnutls_reallocarray(NULL, init, sizeof(gnutls_x509_crl_t)); + if (*crls == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -1272,9 +1272,8 @@ gnutls_x509_crl_list_import2(gnutls_x509_crl_t ** crls, + gnutls_x509_crl_list_import(*crls, &init, data, format, + flags | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { +- *crls = +- gnutls_realloc_fast(*crls, +- sizeof(gnutls_x509_crl_t) * init); ++ *crls = _gnutls_reallocarray_fast(*crls, init, ++ sizeof(gnutls_x509_crl_t)); + if (*crls == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c +index 0c71a6e462..7587a2649a 100644 +--- a/lib/x509/ocsp.c ++++ b/lib/x509/ocsp.c +@@ -1905,9 +1905,8 @@ gnutls_ocsp_resp_get_certs(gnutls_ocsp_resp_const_t resp, + goto error; + } + +- tmpcerts2 = +- gnutls_realloc_fast(tmpcerts, +- (ctr + 2) * sizeof(*tmpcerts)); ++ tmpcerts2 = _gnutls_reallocarray_fast(tmpcerts, ctr + 2, ++ sizeof(*tmpcerts)); + if (tmpcerts2 == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; +@@ -2458,7 +2457,9 @@ gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, + goto fail; + } + +- new_ocsps = gnutls_realloc(*ocsps, (*size + 1)*sizeof(gnutls_ocsp_resp_t)); ++ new_ocsps = _gnutls_reallocarray(*ocsps, ++ *size + 1, ++ sizeof(gnutls_ocsp_resp_t)); + if (new_ocsps == NULL) { + resp = NULL; + gnutls_assert(); +@@ -2492,7 +2493,7 @@ gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, + goto cleanup; + } + +- *ocsps = gnutls_malloc(1*sizeof(gnutls_ocsp_resp_t)); ++ *ocsps = gnutls_malloc(sizeof(gnutls_ocsp_resp_t)); + if (*ocsps == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; +diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c +index 2dc0823905..ac0d2f565f 100644 +--- a/lib/x509/pkcs12.c ++++ b/lib/x509/pkcs12.c +@@ -1455,10 +1455,9 @@ static int make_chain(gnutls_x509_crt_t ** chain, unsigned int *chain_len, + != 0) + goto skip; + +- *chain = +- gnutls_realloc_fast(*chain, +- sizeof((*chain)[0]) * +- ++(*chain_len)); ++ *chain = _gnutls_reallocarray_fast(*chain, ++ ++(*chain_len), ++ sizeof((*chain)[0])); + if (*chain == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -1779,11 +1778,9 @@ gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, + + if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ + _extra_certs = +- gnutls_realloc_fast +- (_extra_certs, +- sizeof(_extra_certs +- [0]) * +- ++_extra_certs_len); ++ _gnutls_reallocarray_fast(_extra_certs, ++ ++_extra_certs_len, ++ sizeof(_extra_certs[0])); + if (!_extra_certs) { + gnutls_assert(); + ret = +diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c +index 736326ee18..7fdbdc68d5 100644 +--- a/lib/x509/verify-high.c ++++ b/lib/x509/verify-high.c +@@ -129,9 +129,9 @@ cert_set_add(struct cert_set_st *set, const gnutls_x509_crt_t cert) + hash %= set->size; + + set->node[hash].certs = +- gnutls_realloc_fast(set->node[hash].certs, +- (set->node[hash].size + 1) * +- sizeof(*set->node[hash].certs)); ++ _gnutls_reallocarray_fast(set->node[hash].certs, ++ set->node[hash].size + 1, ++ sizeof(*set->node[hash].certs)); + if (!set->node[hash].certs) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +@@ -298,10 +298,9 @@ trust_list_add_compat(gnutls_x509_trust_list_t list, + gnutls_x509_crt_t cert) + { + list->keep_certs = +- gnutls_realloc_fast(list->keep_certs, +- (list->keep_certs_size + +- 1) * +- sizeof(list->keep_certs[0])); ++ _gnutls_reallocarray_fast(list->keep_certs, ++ list->keep_certs_size + 1, ++ sizeof(list->keep_certs[0])); + if (list->keep_certs == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -380,11 +379,9 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list, + } + + list->node[hash].trusted_cas = +- gnutls_realloc_fast(list->node[hash].trusted_cas, +- (list->node[hash].trusted_ca_size + +- 1) * +- sizeof(list->node[hash]. +- trusted_cas[0])); ++ _gnutls_reallocarray_fast(list->node[hash].trusted_cas, ++ list->node[hash].trusted_ca_size + 1, ++ sizeof(list->node[hash].trusted_cas[0])); + if (list->node[hash].trusted_cas == NULL) { + gnutls_assert(); + return i; +@@ -671,9 +668,9 @@ gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list, + * ensure that a server certificate will also get rejected. + */ + list->blacklisted = +- gnutls_realloc_fast(list->blacklisted, +- (list->blacklisted_size + 1) * +- sizeof(list->blacklisted[0])); ++ _gnutls_reallocarray_fast(list->blacklisted, ++ list->blacklisted_size + 1, ++ sizeof(list->blacklisted[0])); + if (list->blacklisted == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + +@@ -729,10 +726,9 @@ gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list, + hash %= list->size; + + list->node[hash].named_certs = +- gnutls_realloc_fast(list->node[hash].named_certs, +- (list->node[hash].named_cert_size + +- 1) * +- sizeof(list->node[hash].named_certs[0])); ++ _gnutls_reallocarray_fast(list->node[hash].named_certs, ++ list->node[hash].named_cert_size + 1, ++ sizeof(list->node[hash].named_certs[0])); + if (list->node[hash].named_certs == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + +@@ -842,12 +838,9 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, + } + } + +- tmp = +- gnutls_realloc(list->node[hash].crls, +- (list->node[hash].crl_size + +- 1) * +- sizeof(list->node[hash]. +- crls[0])); ++ tmp = _gnutls_reallocarray(list->node[hash].crls, ++ list->node[hash].crl_size + 1, ++ sizeof(list->node[hash].crls[0])); + if (tmp == NULL) { + ret = i; + gnutls_assert(); +diff --git a/lib/x509/verify-high2.c b/lib/x509/verify-high2.c +index 9820595e97..16d757cf8a 100644 +--- a/lib/x509/verify-high2.c ++++ b/lib/x509/verify-high2.c +@@ -216,7 +216,8 @@ int add_trust_list_pkcs11_object_url(gnutls_x509_trust_list_t list, const char * + goto cleanup; + } + +- xcrt_list = gnutls_malloc(sizeof(gnutls_x509_crt_t) * pcrt_list_size); ++ xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size, ++ sizeof(gnutls_x509_crt_t)); + if (xcrt_list == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; +@@ -264,7 +265,8 @@ int remove_pkcs11_object_url(gnutls_x509_trust_list_t list, const char *url) + goto cleanup; + } + +- xcrt_list = gnutls_malloc(sizeof(gnutls_x509_crt_t) * pcrt_list_size); ++ xcrt_list = _gnutls_reallocarray(NULL, pcrt_list_size, ++ sizeof(gnutls_x509_crt_t)); + if (xcrt_list == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; +diff --git a/lib/x509/x509.c b/lib/x509/x509.c +index c3801a83f2..4e494d10e0 100644 +--- a/lib/x509/x509.c ++++ b/lib/x509/x509.c +@@ -3700,7 +3700,7 @@ gnutls_x509_crt_list_import2(gnutls_x509_crt_t ** certs, + unsigned int init = 1024; + int ret; + +- *certs = gnutls_malloc(sizeof(gnutls_x509_crt_t) * init); ++ *certs = _gnutls_reallocarray(NULL, init, sizeof(gnutls_x509_crt_t)); + if (*certs == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -3710,9 +3710,8 @@ gnutls_x509_crt_list_import2(gnutls_x509_crt_t ** certs, + gnutls_x509_crt_list_import(*certs, &init, data, format, + flags | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { +- *certs = +- gnutls_realloc_fast(*certs, +- sizeof(gnutls_x509_crt_t) * init); ++ *certs = _gnutls_reallocarray_fast(*certs, init, ++ sizeof(gnutls_x509_crt_t)); + if (*certs == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; +@@ -4375,7 +4374,7 @@ gnutls_x509_crt_list_import_url(gnutls_x509_crt_t **certs, + gnutls_free(issuer.data); + } + +- *certs = gnutls_malloc(total*sizeof(gnutls_x509_crt_t)); ++ *certs = _gnutls_reallocarray(NULL, total, sizeof(gnutls_x509_crt_t)); + if (*certs == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; +diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c +index 6aeb159dba..fda936e8ff 100644 +--- a/lib/x509/x509_ext.c ++++ b/lib/x509/x509_ext.c +@@ -137,7 +137,7 @@ int subject_alt_names_set(struct name_st **names, + void *tmp; + int ret; + +- tmp = gnutls_realloc(*names, (*size + 1) * sizeof((*names)[0])); ++ tmp = _gnutls_reallocarray(*names, *size + 1, sizeof((*names)[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +@@ -2317,9 +2317,8 @@ int crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp, + void *tmp; + + /* new dist point */ +- tmp = +- gnutls_realloc(cdp->points, +- (cdp->size + 1) * sizeof(cdp->points[0])); ++ tmp = _gnutls_reallocarray(cdp->points, cdp->size + 1, ++ sizeof(cdp->points[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +@@ -2734,7 +2733,7 @@ int gnutls_x509_aia_set(gnutls_x509_aia_t aia, + void *tmp; + unsigned indx; + +- tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0])); ++ tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, sizeof(aia->aia[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +@@ -2786,7 +2785,8 @@ static int parse_aia(ASN1_TYPE c2, gnutls_x509_aia_t aia) + } + + indx = aia->size; +- tmp = gnutls_realloc(aia->aia, (aia->size + 1) * sizeof(aia->aia[0])); ++ tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, ++ sizeof(aia->aia[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_18-build-avoid-integer-overflow-in-additions.patch gnutls28-3.7.1/debian/patches/56_18-build-avoid-integer-overflow-in-additions.patch --- gnutls28-3.7.1/debian/patches/56_18-build-avoid-integer-overflow-in-additions.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_18-build-avoid-integer-overflow-in-additions.patch 2021-04-24 09:57:17.000000000 -0500 @@ -0,0 +1,369 @@ +From f79af112029d3146d8b1926561ed5834e95c6666 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 29 Mar 2021 11:06:37 +0200 +Subject: [PATCH 4/5] build: avoid integer overflow in additions + +Signed-off-by: Daiki Ueno +--- + lib/cert-cred.c | 5 +++++ + lib/hello_ext.c | 5 +++++ + lib/pkcs11.c | 6 ++++++ + lib/pkcs11x.c | 6 ++++++ + lib/supplemental.c | 5 +++++ + lib/x509/ocsp.c | 11 +++++++++++ + lib/x509/pkcs12.c | 10 ++++++++++ + lib/x509/verify-high.c | 40 +++++++++++++++++++++++++++++++++++----- + lib/x509/x509_ext.c | 16 ++++++++++++++++ + 9 files changed, 99 insertions(+), 5 deletions(-) + +diff --git a/lib/cert-cred.c b/lib/cert-cred.c +index 3f1041f73b..c9c5f6ed50 100644 +--- a/lib/cert-cred.c ++++ b/lib/cert-cred.c +@@ -43,6 +43,7 @@ + #include "x509/common.h" + #include "dh.h" + #include "cert-cred.h" ++#include "intprops.h" + + + /* +@@ -55,6 +56,10 @@ _gnutls_certificate_credential_append_keypair(gnutls_certificate_credentials_t r + gnutls_pcert_st * crt, + int nr) + { ++ if (unlikely(INT_ADD_OVERFLOW(res->ncerts, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + res->sorted_cert_idx = _gnutls_reallocarray_fast(res->sorted_cert_idx, + res->ncerts + 1, + sizeof(unsigned int)); +diff --git a/lib/hello_ext.c b/lib/hello_ext.c +index 6943d095b3..32385f4c0e 100644 +--- a/lib/hello_ext.c ++++ b/lib/hello_ext.c +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include "intprops.h" + + static void + unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx); +@@ -923,6 +924,10 @@ gnutls_session_ext_register(gnutls_session_t session, + tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS; + } + ++ if (unlikely(INT_ADD_OVERFLOW(session->internals.rexts_size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + exts = _gnutls_reallocarray(session->internals.rexts, + session->internals.rexts_size + 1, + sizeof(*exts)); +diff --git a/lib/pkcs11.c b/lib/pkcs11.c +index 7e8c0570ac..364c0c49a9 100644 +--- a/lib/pkcs11.c ++++ b/lib/pkcs11.c +@@ -40,6 +40,7 @@ + #include "x509/x509_int.h" + + #include ++#include "intprops.h" + + #define MAX_PROVIDERS 16 + +@@ -3291,6 +3292,11 @@ find_multi_objs_cb(struct ck_function_list *module, struct pkcs11_session_info * + unsigned j; + gnutls_datum_t id; + ++ if (unlikely(INT_ADD_OVERFLOW(find_data->current, count))) { ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ goto fail; ++ } ++ + find_data->p_list = + _gnutls_reallocarray_fast(find_data->p_list, + find_data->current + count, +diff --git a/lib/pkcs11x.c b/lib/pkcs11x.c +index 7bb62f64bf..dfaee58a39 100644 +--- a/lib/pkcs11x.c ++++ b/lib/pkcs11x.c +@@ -28,6 +28,7 @@ + #include + #include + #include "pkcs11x.h" ++#include "intprops.h" + + struct find_ext_data_st { + /* in */ +@@ -217,6 +218,11 @@ find_ext_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, + rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &ext); + if (rv == CKR_OK) { + ++ if (unlikely(INT_ADD_OVERFLOW(find_data->exts_size, 1))) { ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ goto cleanup; ++ } ++ + find_data->exts = + _gnutls_reallocarray_fast(find_data->exts, + find_data->exts_size + 1, +diff --git a/lib/supplemental.c b/lib/supplemental.c +index fc9545526a..becb01e50c 100644 +--- a/lib/supplemental.c ++++ b/lib/supplemental.c +@@ -48,6 +48,7 @@ + #include "supplemental.h" + #include "errors.h" + #include "num.h" ++#include "intprops.h" + + typedef struct gnutls_supplemental_entry_st { + char *name; +@@ -252,6 +253,10 @@ _gnutls_supplemental_register(gnutls_supplemental_entry_st *entry) + return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED); + } + ++ if (unlikely(INT_ADD_OVERFLOW(suppfunc_size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + p = _gnutls_reallocarray_fast(suppfunc, suppfunc_size + 1, + sizeof(*suppfunc)); + if (!p) { +diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c +index 7587a2649a..e750ac4724 100644 +--- a/lib/x509/ocsp.c ++++ b/lib/x509/ocsp.c +@@ -38,6 +38,7 @@ + #include + + #include ++#include "intprops.h" + + typedef struct gnutls_ocsp_req_int { + ASN1_TYPE req; +@@ -1905,6 +1906,11 @@ gnutls_ocsp_resp_get_certs(gnutls_ocsp_resp_const_t resp, + goto error; + } + ++ if (unlikely(INT_ADD_OVERFLOW(ctr, 2))) { ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ goto error; ++ } ++ + tmpcerts2 = _gnutls_reallocarray_fast(tmpcerts, ctr + 2, + sizeof(*tmpcerts)); + if (tmpcerts2 == NULL) { +@@ -2457,6 +2463,11 @@ gnutls_ocsp_resp_list_import2(gnutls_ocsp_resp_t **ocsps, + goto fail; + } + ++ if (unlikely(INT_ADD_OVERFLOW(*size, 1))) { ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ goto fail; ++ } ++ + new_ocsps = _gnutls_reallocarray(*ocsps, + *size + 1, + sizeof(gnutls_ocsp_resp_t)); +diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c +index ac0d2f565f..965de6fe02 100644 +--- a/lib/x509/pkcs12.c ++++ b/lib/x509/pkcs12.c +@@ -37,6 +37,7 @@ + #include "x509_int.h" + #include "pkcs7_int.h" + #include ++#include "intprops.h" + + + /* Decodes the PKCS #12 auth_safe, and returns the allocated raw data, +@@ -1455,6 +1456,10 @@ static int make_chain(gnutls_x509_crt_t ** chain, unsigned int *chain_len, + != 0) + goto skip; + ++ if (unlikely(INT_ADD_OVERFLOW(*chain_len, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + *chain = _gnutls_reallocarray_fast(*chain, + ++(*chain_len), + sizeof((*chain)[0])); +@@ -1777,6 +1782,11 @@ gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, + } + + if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ ++ if (unlikely(INT_ADD_OVERFLOW(_extra_certs_len, 1))) { ++ ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ goto done; ++ } ++ + _extra_certs = + _gnutls_reallocarray_fast(_extra_certs, + ++_extra_certs_len, +diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c +index 7fdbdc68d5..ab8e006ca7 100644 +--- a/lib/x509/verify-high.c ++++ b/lib/x509/verify-high.c +@@ -34,6 +34,7 @@ + #include + #include + #include "verify-high.h" ++#include "intprops.h" + + struct named_cert_st { + gnutls_x509_crt_t cert; +@@ -128,6 +129,10 @@ cert_set_add(struct cert_set_st *set, const gnutls_x509_crt_t cert) + hash = hash_pjw_bare(cert->raw_dn.data, cert->raw_dn.size); + hash %= set->size; + ++ if (unlikely(INT_ADD_OVERFLOW(set->node[hash].size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + set->node[hash].certs = + _gnutls_reallocarray_fast(set->node[hash].certs, + set->node[hash].size + 1, +@@ -297,6 +302,10 @@ static int + trust_list_add_compat(gnutls_x509_trust_list_t list, + gnutls_x509_crt_t cert) + { ++ if (unlikely(INT_ADD_OVERFLOW(list->keep_certs_size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + list->keep_certs = + _gnutls_reallocarray_fast(list->keep_certs, + list->keep_certs_size + 1, +@@ -378,6 +387,11 @@ gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list, + } + } + ++ if (unlikely(INT_ADD_OVERFLOW(list->node[hash].trusted_ca_size, 1))) { ++ gnutls_assert(); ++ return i; ++ } ++ + list->node[hash].trusted_cas = + _gnutls_reallocarray_fast(list->node[hash].trusted_cas, + list->node[hash].trusted_ca_size + 1, +@@ -663,6 +677,10 @@ gnutls_x509_trust_list_remove_cas(gnutls_x509_trust_list_t list, + } + } + ++ if (unlikely(INT_ADD_OVERFLOW(list->blacklisted_size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + /* Add the CA (or plain) certificate to the black list as well. + * This will prevent a subordinate CA from being valid, and + * ensure that a server certificate will also get rejected. +@@ -725,6 +743,10 @@ gnutls_x509_trust_list_add_named_crt(gnutls_x509_trust_list_t list, + cert->raw_issuer_dn.size); + hash %= list->size; + ++ if (unlikely(INT_ADD_OVERFLOW(list->node[hash].named_cert_size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + list->node[hash].named_certs = + _gnutls_reallocarray_fast(list->node[hash].named_certs, + list->node[hash].named_cert_size + 1, +@@ -838,16 +860,17 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, + } + } + ++ if (unlikely(INT_ADD_OVERFLOW(list->node[hash].crl_size, 1))) { ++ gnutls_assert(); ++ goto error; ++ } ++ + tmp = _gnutls_reallocarray(list->node[hash].crls, + list->node[hash].crl_size + 1, + sizeof(list->node[hash].crls[0])); + if (tmp == NULL) { +- ret = i; + gnutls_assert(); +- if (flags & GNUTLS_TL_NO_DUPLICATES) +- while (i < crl_size) +- gnutls_x509_crl_deinit(crl_list[i++]); +- return ret; ++ goto error; + } + list->node[hash].crls = tmp; + +@@ -861,6 +884,13 @@ gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, + } + + return j; ++ ++ error: ++ ret = i; ++ if (flags & GNUTLS_TL_NO_DUPLICATES) ++ while (i < crl_size) ++ gnutls_x509_crl_deinit(crl_list[i++]); ++ return ret; + } + + /* Takes a certificate list and shortens it if there are +diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c +index fda936e8ff..387f5fbea2 100644 +--- a/lib/x509/x509_ext.c ++++ b/lib/x509/x509_ext.c +@@ -31,6 +31,7 @@ + #include "x509_ext_int.h" + #include "virt-san.h" + #include ++#include "intprops.h" + + #define MAX_ENTRIES 64 + struct gnutls_subject_alt_names_st { +@@ -137,6 +138,10 @@ int subject_alt_names_set(struct name_st **names, + void *tmp; + int ret; + ++ if (unlikely(INT_ADD_OVERFLOW(*size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + tmp = _gnutls_reallocarray(*names, *size + 1, sizeof((*names)[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); +@@ -2316,6 +2321,10 @@ int crl_dist_points_set(gnutls_x509_crl_dist_points_t cdp, + { + void *tmp; + ++ if (unlikely(INT_ADD_OVERFLOW(cdp->size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + /* new dist point */ + tmp = _gnutls_reallocarray(cdp->points, cdp->size + 1, + sizeof(cdp->points[0])); +@@ -2733,6 +2742,10 @@ int gnutls_x509_aia_set(gnutls_x509_aia_t aia, + void *tmp; + unsigned indx; + ++ if (unlikely(INT_ADD_OVERFLOW(aia->size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } ++ + tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, sizeof(aia->aia[0])); + if (tmp == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); +@@ -2785,6 +2798,9 @@ static int parse_aia(ASN1_TYPE c2, gnutls_x509_aia_t aia) + } + + indx = aia->size; ++ if (unlikely(INT_ADD_OVERFLOW(aia->size, 1))) { ++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ++ } + tmp = _gnutls_reallocarray(aia->aia, aia->size + 1, + sizeof(aia->aia[0])); + if (tmp == NULL) { +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_19-_gnutls_calloc-remove-unused-function.patch gnutls28-3.7.1/debian/patches/56_19-_gnutls_calloc-remove-unused-function.patch --- gnutls28-3.7.1/debian/patches/56_19-_gnutls_calloc-remove-unused-function.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_19-_gnutls_calloc-remove-unused-function.patch 2021-04-24 09:57:17.000000000 -0500 @@ -0,0 +1,55 @@ +From 043d1bc387238139a4c2b7f7a6fffdac97ab2b73 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 30 Mar 2021 13:39:46 +0200 +Subject: [PATCH 5/5] _gnutls_calloc: remove unused function + +Signed-off-by: Daiki Ueno +--- + lib/mem.c | 11 ----------- + lib/mem.h | 1 - + 2 files changed, 12 deletions(-) + +diff --git a/lib/mem.c b/lib/mem.c +index 9a74456dbb..c6a78b1edd 100644 +--- a/lib/mem.c ++++ b/lib/mem.c +@@ -23,7 +23,6 @@ + #include "gnutls_int.h" + #include "errors.h" + #include +-#include + #include "xalloc-oversized.h" + + gnutls_alloc_function gnutls_secure_malloc = malloc; +@@ -34,16 +33,6 @@ gnutls_realloc_function gnutls_realloc = realloc; + void *(*gnutls_calloc) (size_t, size_t) = calloc; + char *(*gnutls_strdup) (const char *) = _gnutls_strdup; + +-void *_gnutls_calloc(size_t nmemb, size_t size) +-{ +- void *ret; +- size_t n = xtimes(nmemb, size); +- ret = (size_in_bounds_p(n) ? gnutls_malloc(n) : NULL); +- if (ret != NULL) +- memset(ret, 0, size); +- return ret; +-} +- + /* This realloc will free ptr in case realloc + * fails. + */ +diff --git a/lib/mem.h b/lib/mem.h +index 13f47f17b4..10a8db742d 100644 +--- a/lib/mem.h ++++ b/lib/mem.h +@@ -31,7 +31,6 @@ + void *gnutls_realloc_fast(void *ptr, size_t size); + void *_gnutls_reallocarray_fast(void *ptr, size_t nmemb, size_t size); + +-void *_gnutls_calloc(size_t nmemb, size_t size); + char *_gnutls_strdup(const char *); + + void *_gnutls_reallocarray(void *, size_t, size_t); +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch gnutls28-3.7.1/debian/patches/56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch --- gnutls28-3.7.1/debian/patches/56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch 2021-04-24 10:00:28.000000000 -0500 @@ -0,0 +1,328 @@ +From dc1defac66c2bc654a1aa49222ce268aff74cb75 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Fri, 16 Apr 2021 13:56:40 +0200 +Subject: [PATCH] priority: add option to disable TLS 1.3 middlebox + compatibility mode + +This adds a new option %DISABLE_TLS13_COMPAT_MODE to disable TLS 1.3 +compatibility mode at run-time. + +Signed-off-by: Daiki Ueno +--- + .gitignore | 1 + + NEWS | 5 ++ + doc/cha-gtls-app.texi | 4 ++ + lib/gnutls_int.h | 1 + + lib/handshake-tls13.c | 23 +++--- + lib/handshake.c | 4 +- + lib/priority.c | 9 +++ + lib/priority_options.gperf | 1 + + tests/Makefile.am | 2 +- + tests/tls13-compat-mode.c | 140 +++++++++++++++++++++++++++++++++++++ + 10 files changed, 179 insertions(+), 11 deletions(-) + create mode 100644 tests/tls13-compat-mode.c + +diff --git a/NEWS b/NEWS +index ba6827358d..b3590a316a 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,11 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2013-2019 Nikos Mavrogiannopoulos + See the end for copying conditions. + ++* Version 3.7.2 (unreleased) ++ ++** libgnutls: The priority string option %DISABLE_TLS13_COMPAT_MODE was added ++ to disable TLS 1.3 middlebox compatibility mode ++ + * Version 3.7.1 (released 2021-03-10) + + ** libgnutls: Fixed potential use-after-free in sending "key_share" +diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi +index 36ba55e3ab..2399bf82eb 100644 +--- a/doc/cha-gtls-app.texi ++++ b/doc/cha-gtls-app.texi +@@ -1610,6 +1610,10 @@ client hello. Note that this should be set only by applications that + try to reconnect with a downgraded protocol version. See RFC7507 for + details. + ++@item %DISABLE_TLS13_COMPAT_MODE @tab ++will disable TLS 1.3 middlebox compatibility mode (RFC8446, Appendix ++D.4) for non-compliant middleboxes. ++ + @item %VERIFY_ALLOW_BROKEN @tab + will allow signatures with known to be broken algorithms (such as MD5 or + SHA1) in certificate chains. +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h +index 2611b5af54..62a061e67a 100644 +--- a/lib/gnutls_int.h ++++ b/lib/gnutls_int.h +@@ -950,6 +950,7 @@ struct gnutls_priority_st { + bool have_psk; + bool force_etm; + unsigned int additional_verify_flags; ++ bool tls13_compat_mode; + + /* TLS_FALLBACK_SCSV */ + bool fallback; +diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c +index 7dd42becf1..9687707a32 100644 +--- a/lib/handshake-tls13.c ++++ b/lib/handshake-tls13.c +@@ -84,11 +84,13 @@ int _gnutls13_handshake_client(gnutls_session_t session) + case STATE99: + case STATE100: + #ifdef TLS13_APPENDIX_D4 +- /* We send it before keys are generated. That works because CCS +- * is always being cached and queued and not being sent directly */ +- ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100)); +- STATE = STATE100; +- IMED_RET("send change cipher spec", ret, 0); ++ if (session->internals.priorities->tls13_compat_mode) { ++ /* We send it before keys are generated. That works because CCS ++ * is always being cached and queued and not being sent directly */ ++ ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100)); ++ STATE = STATE100; ++ IMED_RET("send change cipher spec", ret, 0); ++ } + #endif + FALLTHROUGH; + case STATE101: +@@ -385,9 +387,11 @@ int _gnutls13_handshake_server(gnutls_session_t session) + FALLTHROUGH; + case STATE92: + #ifdef TLS13_APPENDIX_D4 +- ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE92)); +- STATE = STATE92; +- IMED_RET("send change cipher spec", ret, 0); ++ if (session->internals.priorities->tls13_compat_mode) { ++ ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE92)); ++ STATE = STATE92; ++ IMED_RET("send change cipher spec", ret, 0); ++ } + #endif + FALLTHROUGH; + case STATE93: +@@ -416,7 +420,8 @@ int _gnutls13_handshake_server(gnutls_session_t session) + #ifdef TLS13_APPENDIX_D4 + /* don't send CCS twice: when HRR has already been + * sent, CCS should have followed it (see above) */ +- if (!(session->internals.hsk_flags & HSK_HRR_SENT)) { ++ if (session->internals.priorities->tls13_compat_mode && ++ !(session->internals.hsk_flags & HSK_HRR_SENT)) { + ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100)); + STATE = STATE100; + IMED_RET("send change cipher spec", ret, 0); +diff --git a/lib/handshake.c b/lib/handshake.c +index 6c894eb68a..33bc7f7be6 100644 +--- a/lib/handshake.c ++++ b/lib/handshake.c +@@ -2213,7 +2213,9 @@ static int send_client_hello(gnutls_session_t session, int again) + } + + #ifdef TLS13_APPENDIX_D4 +- if (max_ver->tls13_sem && !resuming) { ++ if (max_ver->tls13_sem && ++ session->internals.priorities->tls13_compat_mode && ++ !resuming) { + /* Under TLS1.3 we generate a random session ID to make + * the TLS1.3 session look like a resumed TLS1.2 session */ + ret = _gnutls_generate_session_id(session->security_parameters. +diff --git a/lib/priority.c b/lib/priority.c +index 7686c7530a..8cd8a1b260 100644 +--- a/lib/priority.c ++++ b/lib/priority.c +@@ -989,6 +989,10 @@ static void enable_server_precedence(gnutls_priority_t c) + { + c->server_precedence = 1; + } ++static void disable_tls13_compat_mode(gnutls_priority_t c) ++{ ++ c->tls13_compat_mode = false; ++} + static void dummy_func(gnutls_priority_t c) + { + } +@@ -2005,6 +2009,11 @@ gnutls_priority_init(gnutls_priority_t * priority_cache, + * when we make it the default. + */ + (*priority_cache)->sr = SR_PARTIAL; ++ /* For now TLS 1.3 middlebox compatibility mode is enabled by default. ++ * This will eventually be disabled by default and moved to the %COMPAT ++ * setting. ++ */ ++ (*priority_cache)->tls13_compat_mode = true; + (*priority_cache)->min_record_version = 1; + gnutls_atomic_init(&(*priority_cache)->usage_cnt); + +diff --git a/lib/priority_options.gperf b/lib/priority_options.gperf +index a81001dda1..6fb9ae603c 100644 +--- a/lib/priority_options.gperf ++++ b/lib/priority_options.gperf +@@ -39,3 +39,4 @@ PROFILE_SUITEB192, enable_profile_suiteb192 + NEW_PADDING, dummy_func + DEBUG_ALLOW_KEY_USAGE_VIOLATIONS, enable_server_key_usage_violations + ALLOW_SMALL_RECORDS, enable_allow_small_records ++DISABLE_TLS13_COMPAT_MODE, disable_tls13_compat_mode +diff --git a/tests/Makefile.am b/tests/Makefile.am +index c6d994f877..ed32dadcc5 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -223,7 +223,7 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei + sign-verify-newapi sign-verify-deterministic iov aead-cipher-vec \ + tls13-without-timeout-func buffer status-request-revoked \ + set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \ +- x509cert-dntypes id-on-xmppAddr ++ x509cert-dntypes id-on-xmppAddr tls13-compat-mode + + if HAVE_SECCOMP_TESTS + ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp +diff --git a/tests/tls13-compat-mode.c b/tests/tls13-compat-mode.c +new file mode 100644 +index 0000000000..e8f99802df +--- /dev/null ++++ b/tests/tls13-compat-mode.c +@@ -0,0 +1,140 @@ ++/* ++ * Copyright (C) 2021 Free Software Foundation, Inc. ++ * ++ * Author: Daiki Ueno ++ * ++ * This file is part of GnuTLS. ++ * ++ * GnuTLS is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GnuTLS is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GnuTLS. If not, see . ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "cert-common.h" ++#include "eagain-common.h" ++#include "utils.h" ++ ++/* This tests TLS 1.3 middlebox compatibility mode. */ ++ ++#define COMPAT_PRIO "NORMAL:-VERS-ALL:+VERS-TLS1.3" ++#define NO_COMPAT_PRIO COMPAT_PRIO ":%DISABLE_TLS13_COMPAT_MODE" ++ ++#define HANDSHAKE_SESSION_ID_POS 34 ++ ++struct data { ++ bool compat; ++}; ++ ++static int ++handshake_callback(gnutls_session_t session, unsigned int htype, ++ unsigned post, unsigned int incoming, ++ const gnutls_datum_t *msg) ++{ ++ unsigned pos; ++ struct data *data; ++ uint8_t s; ++ ++ assert(htype == GNUTLS_HANDSHAKE_CLIENT_HELLO); ++ assert(msg->size >= HANDSHAKE_SESSION_ID_POS); ++ ++ data = gnutls_session_get_ptr(session); ++ ++ pos = HANDSHAKE_SESSION_ID_POS; ++ if (pos + 1 > msg->size) ++ fail("error\n"); ++ s = msg->data[pos]; ++ ++ if (data->compat && s == 0) { ++ fail("empty session ID while compat mode is enabled\n"); ++ } else if (!data->compat && s > 0) { ++ fail("non-empty session ID while compat mode is disabled\n"); ++ } ++ ++ return 0; ++} ++ ++static void ++test(const char *name, bool client_compat, bool server_compat) ++{ ++ /* Server stuff. */ ++ gnutls_certificate_credentials_t serverx509cred; ++ gnutls_session_t server; ++ int sret = GNUTLS_E_AGAIN; ++ /* Client stuff. */ ++ gnutls_certificate_credentials_t clientx509cred; ++ gnutls_session_t client; ++ struct data data; ++ int cret = GNUTLS_E_AGAIN; ++ ++ success("%s\n", name); ++ ++ /* Init server */ ++ assert(gnutls_certificate_allocate_credentials(&serverx509cred) >= 0); ++ gnutls_certificate_set_x509_key_mem(serverx509cred, ++ &server_cert, &server_key, ++ GNUTLS_X509_FMT_PEM); ++ ++ assert(gnutls_init(&server, GNUTLS_SERVER) >= 0); ++ assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred) >= 0); ++ assert(gnutls_priority_set_direct(server, ++ server_compat ? ++ COMPAT_PRIO : NO_COMPAT_PRIO, ++ NULL) >= 0); ++ gnutls_transport_set_push_function(server, server_push); ++ gnutls_transport_set_pull_function(server, server_pull); ++ gnutls_transport_set_ptr(server, server); ++ ++ /* Init client */ ++ assert(gnutls_certificate_allocate_credentials(&clientx509cred) >= 0); ++ assert(gnutls_init(&client, GNUTLS_CLIENT) >= 0); ++ assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ++ clientx509cred) >= 0); ++ ++ assert(gnutls_priority_set_direct(client, ++ client_compat ? ++ COMPAT_PRIO : NO_COMPAT_PRIO, ++ NULL) >= 0); ++ gnutls_transport_set_push_function(client, client_push); ++ gnutls_transport_set_pull_function(client, client_pull); ++ gnutls_transport_set_ptr(client, client); ++ data.compat = client_compat; ++ gnutls_session_set_ptr(client, &data); ++ gnutls_handshake_set_hook_function(client, GNUTLS_HANDSHAKE_CLIENT_HELLO, ++ GNUTLS_HOOK_POST, ++ handshake_callback); ++ ++ HANDSHAKE(client, server); ++ ++ gnutls_deinit(client); ++ gnutls_deinit(server); ++ ++ gnutls_certificate_free_credentials(serverx509cred); ++ gnutls_certificate_free_credentials(clientx509cred); ++} ++ ++void doit(void) ++{ ++ test("client compat, server compat", true, true); ++ test("client compat, server non-compat", true, false); ++ test("client non-compat, server compat", false, true); ++ test("client non-compat, server non-compat", false, false); ++} +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch gnutls28-3.7.1/debian/patches/56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch --- gnutls28-3.7.1/debian/patches/56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch 2021-04-24 09:59:44.000000000 -0500 @@ -0,0 +1,97 @@ +From 24c9a24640c137b47bb1e8cc5fee2315f57219ad Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 22 Apr 2021 16:42:01 +0200 +Subject: [PATCH] handshake: don't regenerate legacy_session_id in second CH + after HRR + +According to RFC 8446 4.1.2, the client must send the same Client +Hello after Hello Retry Request, except for the certain extensions, +and thus legacy_session_id must be preserved. + +Signed-off-by: Daiki Ueno +--- + lib/handshake.c | 20 +++++++++++--------- + tests/tls13/hello_retry_request.c | 20 ++++++++++++++++++++ + 2 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/lib/handshake.c b/lib/handshake.c +index 33bc7f7be6..c30703ccbd 100644 +--- a/lib/handshake.c ++++ b/lib/handshake.c +@@ -2216,15 +2216,17 @@ static int send_client_hello(gnutls_session_t session, int again) + if (max_ver->tls13_sem && + session->internals.priorities->tls13_compat_mode && + !resuming) { +- /* Under TLS1.3 we generate a random session ID to make +- * the TLS1.3 session look like a resumed TLS1.2 session */ +- ret = _gnutls_generate_session_id(session->security_parameters. +- session_id, +- &session->security_parameters. +- session_id_size); +- if (ret < 0) { +- gnutls_assert(); +- goto cleanup; ++ if (!(session->internals.hsk_flags & HSK_HRR_RECEIVED)) { ++ /* Under TLS1.3 we generate a random session ID to make ++ * the TLS1.3 session look like a resumed TLS1.2 session */ ++ ret = _gnutls_generate_session_id(session->security_parameters. ++ session_id, ++ &session->security_parameters. ++ session_id_size); ++ if (ret < 0) { ++ gnutls_assert(); ++ goto cleanup; ++ } + } + session_id = session->security_parameters.session_id; + session_id_len = session->security_parameters.session_id_size; +diff --git a/tests/tls13/hello_retry_request.c b/tests/tls13/hello_retry_request.c +index f90d4ad676..dd4506b6f9 100644 +--- a/tests/tls13/hello_retry_request.c ++++ b/tests/tls13/hello_retry_request.c +@@ -69,9 +69,13 @@ static void client_log_func(int level, const char *str) + fprintf(stderr, "client|<%d>| %s", level, str); + } + ++#define HANDSHAKE_SESSION_ID_POS 34 ++ + struct ctx_st { + unsigned hrr_seen; + unsigned hello_counter; ++ uint8_t session_id[32]; ++ size_t session_id_len; + }; + + static int hello_callback(gnutls_session_t session, unsigned int htype, +@@ -84,12 +88,28 @@ static int hello_callback(gnutls_session_t session, unsigned int htype, + ctx->hrr_seen = 1; + + if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && post == GNUTLS_HOOK_POST) { ++ size_t session_id_len; ++ uint8_t *session_id; ++ ++ assert(msg->size > HANDSHAKE_SESSION_ID_POS + 1); ++ session_id_len = msg->data[HANDSHAKE_SESSION_ID_POS]; ++ session_id = &msg->data[HANDSHAKE_SESSION_ID_POS + 1]; ++ + if (ctx->hello_counter > 0) { + assert(msg->size > 4); + if (msg->data[0] != 0x03 || msg->data[1] != 0x03) { + fail("version is %d.%d expected 3,3\n", (int)msg->data[0], (int)msg->data[1]); + } ++ ++ if (session_id_len != ctx->session_id_len || ++ memcmp(session_id, ctx->session_id, session_id_len) != 0) { ++ fail("different legacy_session_id is sent after HRR\n"); ++ } + } ++ ++ ctx->session_id_len = session_id_len; ++ memcpy(ctx->session_id, session_id, session_id_len); ++ + ctx->hello_counter++; + } + +-- +2.30.2 + diff -Nru gnutls28-3.7.1/debian/patches/56_28-handshake-fix-timing-of-sending-early-data.patch gnutls28-3.7.1/debian/patches/56_28-handshake-fix-timing-of-sending-early-data.patch --- gnutls28-3.7.1/debian/patches/56_28-handshake-fix-timing-of-sending-early-data.patch 1969-12-31 18:00:00.000000000 -0600 +++ gnutls28-3.7.1/debian/patches/56_28-handshake-fix-timing-of-sending-early-data.patch 2021-04-25 05:55:14.000000000 -0500 @@ -0,0 +1,600 @@ +From 0e1f1f0558e733c39a55172fecbb42c96abc31d3 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Fri, 23 Apr 2021 15:36:37 +0200 +Subject: [PATCH] handshake: fix timing of sending early data + +Previously, the client was sending early data after receiving a Server +Hello message, which not only negates the benefit of 0-RTT, but also +was a logic error as it can only be decrypted by the server when the +initial handshake and the resuming handshake agree on the same +ciphersuites. This fixes that behavior in the following ways: + +- extend the session data format to include the selected ciphersuites, + even in TLS 1.3 +- setup the epoch for early data, right before the client sending + early data (also right after the server deciding to accept early + data). +- extend the test case to use different ciphersuites in the initial + and resuming handshakes + +Signed-off-by: Daiki Ueno +--- + NEWS | 5 +++ + lib/cipher.c | 6 ++- + lib/constate.c | 46 +++++++++++++++++--- + lib/handshake-tls13.c | 92 ++++++++++++++-------------------------- + lib/handshake.c | 70 ++++++++++++++++++++++++++++++ + lib/record.c | 2 +- + lib/session_pack.c | 14 +++--- + tests/tls13-early-data.c | 16 +++++-- + tests/tls13/prf-early.c | 8 ++-- + 9 files changed, 176 insertions(+), 83 deletions(-) + +--- a/NEWS ++++ b/NEWS +@@ -8,10 +8,15 @@ + * Version 3.7.2 (unreleased) + + ** libgnutls: The priority string option %DISABLE_TLS13_COMPAT_MODE was added + to disable TLS 1.3 middlebox compatibility mode + ++** libgnutls: Fixed timing of early data exchange. Previously, the client was ++ sending early data after receiving Server Hello, which not only negates the ++ benefit of 0-RTT, but also works under certain assumptions hold (e.g., the ++ same ciphersuite is selected in initial and resumption handshake) (#1146). ++ + * Version 3.7.1 (released 2021-03-10) + + ** libgnutls: Fixed potential use-after-free in sending "key_share" + and "pre_shared_key" extensions. When sending those extensions, the + client may dereference a pointer no longer valid after +--- a/lib/cipher.c ++++ b/lib/cipher.c +@@ -83,11 +83,15 @@ + size_t min_pad, + mbuffer_st *bufel, + content_type_t type, record_parameters_st *params) + { + gnutls_datum_t plaintext; +- const version_entry_st *vers = get_version(session); ++ const version_entry_st *vers = ++ (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) && ++ !IS_SERVER(session) ? ++ session->internals.resumed_security_parameters.pversion : ++ get_version(session); + int ret; + + plaintext.data = (uint8_t *) data; + plaintext.size = data_size; + +--- a/lib/constate.c ++++ b/lib/constate.c +@@ -334,15 +334,23 @@ + if (session->security_parameters.entity == GNUTLS_CLIENT && + !(session->internals.hsk_flags & HSK_TLS13_TICKET_SENT)) { + return GNUTLS_E_INVALID_REQUEST; + } + +- ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.proto.tls13.e_ckey, key_size, key_block); ++ ret = _tls13_expand_secret2(session->internals. ++ resumed_security_parameters.prf, ++ "key", 3, NULL, 0, ++ session->key.proto.tls13.e_ckey, ++ key_size, key_block); + if (ret < 0) + return gnutls_assert_val(ret); + +- ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.e_ckey, iv_size, iv_block); ++ ret = _tls13_expand_secret2(session->internals. ++ resumed_security_parameters.prf, ++ "iv", 2, NULL, 0, ++ session->key.proto.tls13.e_ckey, ++ iv_size, iv_block); + if (ret < 0) + return gnutls_assert_val(ret); + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + early_state = ¶ms->write; +@@ -590,14 +598,23 @@ + if (params->initialized && (params->cipher != cipher_algo || + params->mac != mac_algo || cs != session->security_parameters.cs)) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + return 0; +- } else { +- if (params->initialized +- || params->cipher != NULL || params->mac != NULL) +- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ } ++ ++ /* The params shouldn't have been initialized at this point, unless we ++ * are doing trial encryption/decryption of early data. ++ */ ++ if (unlikely ++ (!((session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT && ++ !IS_SERVER(session)) || ++ (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED && ++ IS_SERVER(session))) && ++ (params->initialized ++ || params->cipher != NULL || params->mac != NULL))) { ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } + + if (_gnutls_cipher_is_ok(cipher_algo) == 0 + || _gnutls_mac_is_ok(mac_algo) == 0) + return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); +@@ -653,11 +670,14 @@ + int hash_size; + int IV_size; + int key_size; + record_parameters_st *params; + int ret; +- const version_entry_st *ver = get_version(session); ++ const version_entry_st *ver = ++ stage == STAGE_EARLY && !IS_SERVER(session) ? ++ session->internals.resumed_security_parameters.pversion : ++ get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = _gnutls_epoch_get(session, epoch, ¶ms); +@@ -1198,16 +1218,22 @@ + { + const uint16_t epoch_next = + session->security_parameters.epoch_next; + int ret; + ++ if (unlikely(stage == STAGE_EARLY && !IS_SERVER(session))) { ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ } ++ + ret = _gnutls_epoch_set_keys(session, epoch_next, stage); + if (ret < 0) + return ret; + + _gnutls_handshake_log("HSK[%p]: TLS 1.3 set read key with cipher suite: %s\n", + session, ++ stage == STAGE_EARLY ? ++ session->internals.resumed_security_parameters.cs->name : + session->security_parameters.cs->name); + + session->security_parameters.epoch_read = epoch_next; + + ret = _gnutls_call_secret_func(session, stage, 1, 0); +@@ -1221,16 +1247,22 @@ + { + const uint16_t epoch_next = + session->security_parameters.epoch_next; + int ret; + ++ if (unlikely(stage == STAGE_EARLY && IS_SERVER(session))) { ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ } ++ + ret = _gnutls_epoch_set_keys(session, epoch_next, stage); + if (ret < 0) + return ret; + + _gnutls_handshake_log("HSK[%p]: TLS 1.3 set write key with cipher suite: %s\n", + session, ++ stage == STAGE_EARLY ? ++ session->internals.resumed_security_parameters.cs->name : + session->security_parameters.cs->name); + + session->security_parameters.epoch_write = epoch_next; + + ret = _gnutls_call_secret_func(session, stage, 0, 1); +--- a/lib/handshake-tls13.c ++++ b/lib/handshake-tls13.c +@@ -82,40 +82,23 @@ + + switch (STATE) { + case STATE99: + case STATE100: + #ifdef TLS13_APPENDIX_D4 +- if (session->internals.priorities->tls13_compat_mode) { ++ if (session->internals.priorities->tls13_compat_mode && ++ /* Key change is indicated by sending an EndOfEarlyData below */ ++ !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) { + /* We send it before keys are generated. That works because CCS + * is always being cached and queued and not being sent directly */ + ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100)); + STATE = STATE100; + IMED_RET("send change cipher spec", ret, 0); + } + #endif + FALLTHROUGH; + case STATE101: +- /* Note that we check IN_FLIGHT, not ACCEPTED +- * here. This is because the client sends early data +- * speculatively. */ +- if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) { +- ret = _tls13_write_connection_state_init(session, STAGE_EARLY); +- if (ret == 0) { +- _gnutls_epoch_bump(session); +- ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT); +- } +- STATE = STATE101; +- IMED_RET_FATAL("set early traffic keys", ret, 0); +- } +- FALLTHROUGH; +- case STATE102: +- ret = _gnutls13_send_early_data(session); +- STATE = STATE102; +- IMED_RET("send early data", ret, 0); +- FALLTHROUGH; +- case STATE103: +- STATE = STATE103; ++ STATE = STATE101; + ret = generate_hs_traffic_keys(session); + /* Note that we check IN_FLIGHT, not ACCEPTED + * here. This is because the client sends early data + * speculatively. */ + IMED_RET_FATAL("generate hs traffic keys", ret, 0); +@@ -123,44 +106,44 @@ + ret = _tls13_read_connection_state_init(session, STAGE_HS); + else + ret = _tls13_connection_state_init(session, STAGE_HS); + IMED_RET_FATAL("set hs traffic keys", ret, 0); + FALLTHROUGH; +- case STATE104: ++ case STATE102: + ret = _gnutls13_recv_encrypted_extensions(session); +- STATE = STATE104; ++ STATE = STATE102; + IMED_RET("recv encrypted extensions", ret, 0); + FALLTHROUGH; +- case STATE105: ++ case STATE103: + ret = _gnutls13_recv_certificate_request(session); +- STATE = STATE105; ++ STATE = STATE103; + IMED_RET("recv certificate request", ret, 0); + FALLTHROUGH; +- case STATE106: ++ case STATE104: + ret = _gnutls13_recv_certificate(session); +- STATE = STATE106; ++ STATE = STATE104; + IMED_RET("recv certificate", ret, 0); + FALLTHROUGH; +- case STATE107: ++ case STATE105: + ret = _gnutls13_recv_certificate_verify(session); +- STATE = STATE107; ++ STATE = STATE105; + IMED_RET("recv server certificate verify", ret, 0); + FALLTHROUGH; +- case STATE108: ++ case STATE106: + ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT); +- STATE = STATE108; ++ STATE = STATE106; + if (ret < 0) + return gnutls_assert_val(ret); + FALLTHROUGH; +- case STATE109: ++ case STATE107: + ret = _gnutls13_recv_finished(session); +- STATE = STATE109; ++ STATE = STATE107; + IMED_RET("recv finished", ret, 0); + FALLTHROUGH; +- case STATE110: +- ret = _gnutls13_send_end_of_early_data(session, AGAIN(STATE110)); +- STATE = STATE110; ++ case STATE108: ++ ret = _gnutls13_send_end_of_early_data(session, AGAIN(STATE108)); ++ STATE = STATE108; + IMED_RET("send end of early data", ret, 0); + + /* Note that we check IN_FLIGHT, not ACCEPTED + * here. This is because the client sends early data + * speculatively. */ +@@ -168,27 +151,27 @@ + session->internals.hsk_flags &= ~HSK_EARLY_DATA_IN_FLIGHT; + ret = _tls13_write_connection_state_init(session, STAGE_HS); + IMED_RET_FATAL("set hs traffic key after sending early data", ret, 0); + } + FALLTHROUGH; +- case STATE111: +- ret = _gnutls13_send_certificate(session, AGAIN(STATE111)); +- STATE = STATE111; ++ case STATE109: ++ ret = _gnutls13_send_certificate(session, AGAIN(STATE109)); ++ STATE = STATE109; + IMED_RET("send certificate", ret, 0); + FALLTHROUGH; +- case STATE112: +- ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE112)); +- STATE = STATE112; ++ case STATE110: ++ ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE110)); ++ STATE = STATE110; + IMED_RET("send certificate verify", ret, 0); + FALLTHROUGH; +- case STATE113: +- ret = _gnutls13_send_finished(session, AGAIN(STATE113)); +- STATE = STATE113; ++ case STATE111: ++ ret = _gnutls13_send_finished(session, AGAIN(STATE111)); ++ STATE = STATE111; + IMED_RET("send finished", ret, 0); + FALLTHROUGH; +- case STATE114: +- STATE = STATE114; ++ case STATE112: ++ STATE = STATE112; + + ret = + generate_ap_traffic_keys(session); + IMED_RET_FATAL("generate app keys", ret, 0); + +@@ -428,26 +411,17 @@ + } + #endif + FALLTHROUGH; + case STATE101: + STATE = STATE101; +- if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { +- ret = _tls13_read_connection_state_init(session, STAGE_EARLY); +- if (ret == 0) { +- _gnutls_epoch_bump(session); +- ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT); +- } +- IMED_RET_FATAL("set early traffic keys", ret, 0); + +- ret = generate_hs_traffic_keys(session); +- IMED_RET_FATAL("generate hs traffic keys", ret, 0); ++ ret = generate_hs_traffic_keys(session); ++ IMED_RET_FATAL("generate hs traffic keys", ret, 0); + ++ if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { + ret = _tls13_write_connection_state_init(session, STAGE_HS); + } else { +- ret = generate_hs_traffic_keys(session); +- IMED_RET_FATAL("generate hs traffic keys", ret, 0); +- + ret = _tls13_connection_state_init(session, STAGE_HS); + } + IMED_RET_FATAL("set hs traffic keys", ret, 0); + FALLTHROUGH; + case STATE102: +--- a/lib/handshake.c ++++ b/lib/handshake.c +@@ -53,10 +53,11 @@ + #include /* for gnutls_anon_server_credentials_t */ + #include /* for gnutls_psk_server_credentials_t */ + #include + #include + #include "secrets.h" ++#include "tls13/early_data.h" + #include "tls13/session_ticket.h" + #include "locks.h" + #ifdef HAVE_VALGRIND_MEMCHECK_H + #include + #endif +@@ -786,10 +787,42 @@ + if (ret < 0) { + gnutls_assert(); + return ret; + } + ++ if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { ++ const cipher_entry_st *ce; ++ const mac_entry_st *me; ++ record_parameters_st *params; ++ ++ ce = cipher_to_entry(session->internals. ++ resumed_security_parameters. ++ cs->block_algorithm); ++ me = mac_to_entry(session->internals. ++ resumed_security_parameters. ++ cs->mac_algorithm); ++ ++ ret = _gnutls_epoch_get(session, EPOCH_NEXT, ¶ms); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ ++ params->cipher = ce; ++ params->mac = me; ++ ++ ret = _tls13_read_connection_state_init(session, STAGE_EARLY); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ ++ _gnutls_epoch_bump(session); ++ ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ } ++ + /* resumed by session_ticket extension */ + if (!vers->tls13_sem && session->internals.resumed) { + session->internals.resumed_security_parameters. + max_record_recv_size = + session->security_parameters.max_record_recv_size; +@@ -2307,10 +2340,47 @@ + } + + ret = _gnutls_send_handshake(session, bufel, + GNUTLS_HANDSHAKE_CLIENT_HELLO); + ++ if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) { ++ const cipher_entry_st *ce; ++ const mac_entry_st *me; ++ record_parameters_st *params; ++ ++ ce = cipher_to_entry(session->internals. ++ resumed_security_parameters. ++ cs->block_algorithm); ++ me = mac_to_entry(session->internals. ++ resumed_security_parameters. ++ cs->mac_algorithm); ++ ++ ret = _gnutls_epoch_get(session, EPOCH_NEXT, ¶ms); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ ++ params->cipher = ce; ++ params->mac = me; ++ ++ ret = _tls13_write_connection_state_init(session, STAGE_EARLY); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ ++ _gnutls_epoch_bump(session); ++ ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ ++ ret = _gnutls13_send_early_data(session); ++ if (ret < 0) { ++ return gnutls_assert_val(ret); ++ } ++ } ++ + return ret; + + cleanup: + _gnutls_buffer_clear(&extdata); + return ret; +--- a/lib/record.c ++++ b/lib/record.c +@@ -2118,11 +2118,11 @@ + * gnutls_record_recv_early_data: + * @session: is a #gnutls_session_t type. + * @data: the buffer that the data will be read into + * @data_size: the number of requested bytes + * +- * This function can be used by a searver to retrieve data sent early ++ * This function can be used by a server to retrieve data sent early + * in the handshake processes when resuming a session. This is used + * to implement a zero-roundtrip (0-RTT) mode. It has the same + * semantics as gnutls_record_recv(). + * + * This function can be called either in a handshake hook, or after +--- a/lib/session_pack.c ++++ b/lib/session_pack.c +@@ -909,15 +909,15 @@ + BUFFER_APPEND_NUM(ps, session->security_parameters.pversion->id); + + BUFFER_APPEND_NUM(ps, session->security_parameters.client_ctype); + BUFFER_APPEND_NUM(ps, session->security_parameters.server_ctype); + ++ BUFFER_APPEND(ps, session->security_parameters.cs->id, 2); ++ + /* 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_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, +@@ -1024,16 +1024,16 @@ + client_ctype); + BUFFER_POP_NUM(ps, + session->internals.resumed_security_parameters. + server_ctype); + +- 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(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); + ++ if (!session->internals.resumed_security_parameters.pversion->tls13_sem) { + /* master secret */ + ret = _gnutls_buffer_pop_datum_prefix8(ps, &t); + if (ret < 0) { + ret = GNUTLS_E_PARSING_ERROR; + gnutls_assert(); +--- a/tests/tls13-early-data.c ++++ b/tests/tls13-early-data.c +@@ -68,15 +68,23 @@ + + + /* A very basic TLS client. + */ + +-#define SESSIONS 3 + #define MAX_BUF 1024 + #define MSG "Hello TLS" + #define EARLY_MSG "Hello TLS, it's early" +-#define PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3" ++ ++/* This test makes connection 3 times with different ciphersuites: first with ++ * TLS_AES_128_GCM_SHA256, then TLS_AES_256_GCM_SHA384 two times. The reason ++ * for doing this is to check that the early data is encrypted with the ++ * ciphersuite selected during the initial handshake, not the resuming ++ * handshakes. ++ */ ++#define SESSIONS 3 ++#define TLS13_AES_128_GCM "NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-128-GCM" ++#define TLS13_AES_256_GCM "NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-256-GCM" + + static const + gnutls_datum_t hrnd = {(void*)"\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32}; + + static int gnutls_rnd_works; +@@ -118,11 +126,11 @@ + + for (t = 0; t < SESSIONS; t++) { + int sd = sds[t]; + + assert(gnutls_init(&session, GNUTLS_CLIENT)>=0); +- assert(gnutls_priority_set_direct(session, PRIORITY, NULL)>=0); ++ assert(gnutls_priority_set_direct(session, t == 0 ? TLS13_AES_128_GCM : TLS13_AES_256_GCM, NULL)>=0); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); + + gnutls_transport_set_int(session, sd); + +@@ -287,11 +295,11 @@ + for (t = 0; t < SESSIONS; t++) { + int sd = sds[t]; + + assert(gnutls_init(&session, GNUTLS_SERVER|GNUTLS_ENABLE_EARLY_DATA)>=0); + +- assert(gnutls_priority_set_direct(session, PRIORITY, NULL)>=0); ++ assert(gnutls_priority_set_direct(session, t == 0 ? TLS13_AES_128_GCM : TLS13_AES_256_GCM, NULL)>=0); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); + + gnutls_session_ticket_enable_server(session, + &session_ticket_key); +--- a/tests/tls13/prf-early.c ++++ b/tests/tls13/prf-early.c +@@ -121,14 +121,14 @@ + dump("expected ", exp, size); \ + exit(1); \ + } \ + } + +-#define KEY_EXP_VALUE "\x7f\x9a\x62\x64\x5e\x90\xa4\x19\x6f\xbf\x7b\x4e\x98\x63\x29\xb0\x46\xa2\x2a\x47\x94\x6a\x78\xdc\x6e\xea\x90\x13\x9d\xd4\xd1\x20\x02\x04" +-#define HELLO_VALUE "\x38\x40\x8c\x0d\x53\xe5\xd2\xe8\x66\xb4\x46\xce\x32\x85\xd5\x02\x3a\x4f\x81\x3c\x9e\x1b\x4a\x53\x73\x22\xad\xf2\x11\xc6\x45" +-#define CONTEXT_VALUE "\xf6\x95\x60\x0d\x51\x9e\x1a\x40\xb2\x9e\xb0\x48\x55\xfe\x64\xf8\xa0\x26\x31\xd8\xb1\x66\xf3\x10\x62\x32\x26\x52\x9e\x63\x49" +-#define NULL_CONTEXT_VALUE "\xb1\x80\x8c\xb3\xc2\xa9\x06\x88\xb7\xc2\xed\xd4\x5f\x1c\xad\x0b\xb2\x1f\xa9\xe2\xc6\x37\xd3\x52\x73\x1b\xf5\x3b\x92\x61\x08" ++#define KEY_EXP_VALUE "\xec\xc2\x4a\x6b\x07\x89\xd9\x19\xd9\x73\x6d\xd0\x00\x73\xc9\x7a\xd7\x92\xef\x56\x91\x61\xb4\xff\x5f\xef\x81\xc1\x98\x68\x4e\xdf\xd7\x7e" ++#define HELLO_VALUE "\x4f\x85\x33\x64\x48\xff\x0d\x8b\xd5\x50\x0f\x97\x91\x5b\x7d\x8d\xc9\x05\x91\x45\x4f\xb9\x4b\x4b\xbc\xbf\x58\x84\x1a\x46\xe3" ++#define CONTEXT_VALUE "\x11\x8d\x85\xa8\x91\xe5\x50\x75\x44\x88\x69\xaf\x95\x9a\xb0\x29\xd4\xae\xcd\x11\xcb\x1d\x29\x7c\xe6\x24\xd4\x7c\x95\xdb\x5c" ++#define NULL_CONTEXT_VALUE "\x56\x99\x41\x73\x5e\x73\x34\x7f\x3d\x69\x9f\xc0\x3b\x8b\x86\x33\xc6\xc3\x97\x46\x61\x62\x3f\x55\xab\x39\x60\xa5\xeb\xfe\x37" + + static int handshake_callback_called; + + static int handshake_callback(gnutls_session_t session, unsigned int htype, + unsigned post, unsigned int incoming, const gnutls_datum_t *msg) diff -Nru gnutls28-3.7.1/debian/patches/series gnutls28-3.7.1/debian/patches/series --- gnutls28-3.7.1/debian/patches/series 2021-04-14 09:25:09.000000000 -0500 +++ gnutls28-3.7.1/debian/patches/series 2021-05-21 10:16:02.000000000 -0500 @@ -10,3 +10,11 @@ 56_05-examples-avoid-memory-leak-in-ex-verify.patch 56_10-build-doc-install-missing-image-file-gnutls-crypto-l.patch 9259100633b77a0dc03f83047d7cf778466bf9f3.patch +56_15-mem-add-_gnutls_reallocarray-and-_gnutls_reallocarra.patch +56_16-pkcs11x-find_ext_cb-fix-error-propagation.patch +56_17-build-avoid-potential-integer-overflow-in-array-allo.patch +56_18-build-avoid-integer-overflow-in-additions.patch +56_19-_gnutls_calloc-remove-unused-function.patch +56_20-priority-add-option-to-disable-TLS-1.3-middlebox-com.patch +56_24-handshake-don-t-regenerate-legacy_session_id-in-seco.patch +56_28-handshake-fix-timing-of-sending-early-data.patch