summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/rootfs-postcommands.bbclass4
-rw-r--r--meta/recipes-core/glibc/glibc-version.inc2
-rw-r--r--meta/recipes-core/glibc/glibc_2.35.bb2
-rw-r--r--meta/recipes-core/images/build-appliance-image_15.0.0.bb2
-rw-r--r--meta/recipes-core/systemd/systemd/fix-vlan-qos-mapping.patch140
-rw-r--r--meta/recipes-core/systemd/systemd_250.5.bb1
-rw-r--r--meta/recipes-devtools/go/go-1.17.13.inc1
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2023-45288.patch95
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2024-27281.patch97
-rw-r--r--meta/recipes-devtools/ruby/ruby_3.1.3.bb1
-rw-r--r--meta/recipes-devtools/rust/rust-source.inc3
-rw-r--r--meta/recipes-devtools/tcltk/tcl/run-ptest4
-rw-r--r--meta/recipes-devtools/valgrind/valgrind/remove-for-all2
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2024-28834.patch457
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2024-28835.patch406
-rw-r--r--meta/recipes-support/gnutls/gnutls_3.7.4.bb2
-rw-r--r--meta/recipes-support/libssh2/libssh2/CVE-2023-48795.patch459
-rw-r--r--meta/recipes-support/libssh2/libssh2_1.10.0.bb1
-rw-r--r--meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0001.patch110
-rw-r--r--meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0002.patch105
-rw-r--r--meta/recipes-support/nghttp2/nghttp2_1.47.0.bb2
21 files changed, 1890 insertions, 6 deletions
diff --git a/meta/classes/rootfs-postcommands.bbclass b/meta/classes/rootfs-postcommands.bbclass
index 5c0b3ec37c..f7517c66dc 100644
--- a/meta/classes/rootfs-postcommands.bbclass
+++ b/meta/classes/rootfs-postcommands.bbclass
@@ -119,7 +119,9 @@ read_only_rootfs_hook () {
# Also tweak the key location for dropbear in the same way.
if [ -d ${IMAGE_ROOTFS}/etc/dropbear ]; then
if [ ! -e ${IMAGE_ROOTFS}/etc/dropbear/dropbear_rsa_host_key ]; then
- echo "DROPBEAR_RSAKEY_DIR=/var/lib/dropbear" >> ${IMAGE_ROOTFS}/etc/default/dropbear
+ if ! grep -q "^DROPBEAR_RSAKEY_DIR=" ${IMAGE_ROOTFS}/etc/default/dropbear ; then
+ echo "DROPBEAR_RSAKEY_DIR=/var/lib/dropbear" >> ${IMAGE_ROOTFS}/etc/default/dropbear
+ fi
fi
fi
fi
diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc
index e0d47f283b..cd8c7ecf94 100644
--- a/meta/recipes-core/glibc/glibc-version.inc
+++ b/meta/recipes-core/glibc/glibc-version.inc
@@ -1,6 +1,6 @@
SRCBRANCH ?= "release/2.35/master"
PV = "2.35"
-SRCREV_glibc ?= "c84018a05aec80f5ee6f682db0da1130b0196aef"
+SRCREV_glibc ?= "36280d1ce5e245aabefb877fe4d3c6cff95dabfa"
SRCREV_localedef ?= "794da69788cbf9bf57b59a852f9f11307663fa87"
GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
diff --git a/meta/recipes-core/glibc/glibc_2.35.bb b/meta/recipes-core/glibc/glibc_2.35.bb
index 751427517f..74d7f753d8 100644
--- a/meta/recipes-core/glibc/glibc_2.35.bb
+++ b/meta/recipes-core/glibc/glibc_2.35.bb
@@ -24,7 +24,7 @@ CVE_CHECK_IGNORE += "CVE-2019-1010025"
CVE_CHECK_IGNORE += "CVE-2023-4527"
# To avoid these in cve-check reports since the recipe version did not change
-CVE_CHECK_IGNORE += "CVE-2023-0687 CVE-2023-4813 CVE-2023-4806 CVE-2023-4911 CVE-2023-5156"
+CVE_CHECK_IGNORE += "CVE-2023-0687 CVE-2023-4813 CVE-2023-4806 CVE-2023-4911 CVE-2023-5156 CVE-2024-2961"
DEPENDS += "gperf-native bison-native"
diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
index aef8b3055b..57274262ba 100644
--- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb
+++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
@@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk wic.vhd wic.vhdx"
inherit core-image setuptools3
-SRCREV ?= "ff7353b24f11f9ba8760f04b678e805fd2590073"
+SRCREV ?= "700eac59a68baaba3361ed40ab14fe55e66f8211"
SRC_URI = "git://git.yoctoproject.org/poky;branch=kirkstone \
file://Yocto_Build_Appliance.vmx \
file://Yocto_Build_Appliance.vmxf \
diff --git a/meta/recipes-core/systemd/systemd/fix-vlan-qos-mapping.patch b/meta/recipes-core/systemd/systemd/fix-vlan-qos-mapping.patch
new file mode 100644
index 0000000000..c530de7f50
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/fix-vlan-qos-mapping.patch
@@ -0,0 +1,140 @@
+From 4d13d175f8454df63843a880c78badd4f6d720ca Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 24 May 2023 11:02:36 +0900
+Subject: [PATCH 1/3] network/vlan: drop unnecessary restriction for QoS
+ mapping
+
+Fixes #27460.
+
+Upstream-Status: Backport [https://github.com/systemd/systemd/commit/fe830b84d4002582e7aefb16e5e09fd0195f21c8.patch]
+Signed-off-by: Sana Kazi <sana.kazi@kpit.com>
+---
+ src/network/netdev/vlan.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/src/network/netdev/vlan.c b/src/network/netdev/vlan.c
+index a3d961dac3ca4..d61e9486abc47 100644
+--- a/src/network/netdev/vlan.c
++++ b/src/network/netdev/vlan.c
+@@ -165,11 +165,6 @@ int config_parse_vlan_qos_maps(
+ continue;
+ }
+
+- if (m->to > m->from || m->to == 0 || m->from == 0) {
+- log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s, ignoring: %s", lvalue, w);
+- continue;
+- }
+-
+ r = set_ensure_consume(s, &vlan_qos_maps_hash_ops, TAKE_PTR(m));
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to store %s, ignoring: %s", lvalue, w);
+
+From 4194478af861f80a73905d1f9e570a09862f91a7 Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 24 May 2023 11:06:35 +0900
+Subject: [PATCH 2/3] network/vlan: paranoia about type safety
+
+No functional change, as the struct is defined as the following:
+```
+struct ifla_vlan_qos_mapping {
+ __u32 from;
+ __u32 to;
+};
+```
+---
+ src/network/netdev/vlan.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/src/network/netdev/vlan.c b/src/network/netdev/vlan.c
+index d61e9486abc47..5eb36ef6801f3 100644
+--- a/src/network/netdev/vlan.c
++++ b/src/network/netdev/vlan.c
+@@ -144,6 +144,7 @@ int config_parse_vlan_qos_maps(
+ for (const char *p = rvalue;;) {
+ _cleanup_free_ struct ifla_vlan_qos_mapping *m = NULL;
+ _cleanup_free_ char *w = NULL;
++ unsigned from, to;
+
+ r = extract_first_word(&p, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
+ if (r == -ENOMEM)
+@@ -155,16 +156,21 @@ int config_parse_vlan_qos_maps(
+ if (r == 0)
+ return 0;
+
+- m = new0(struct ifla_vlan_qos_mapping, 1);
+- if (!m)
+- return log_oom();
+-
+- r = parse_range(w, &m->from, &m->to);
++ r = parse_range(w, &from, &to);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, w);
+ continue;
+ }
+
++ m = new(struct ifla_vlan_qos_mapping, 1);
++ if (!m)
++ return log_oom();
++
++ *m = (struct ifla_vlan_qos_mapping) {
++ .from = from,
++ .to = to,
++ };
++
+ r = set_ensure_consume(s, &vlan_qos_maps_hash_ops, TAKE_PTR(m));
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to store %s, ignoring: %s", lvalue, w);
+
+From 73d24e45f8ac18eaaebf1df2b1f055c14179c6ff Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Wed, 24 May 2023 11:15:44 +0900
+Subject: [PATCH 3/3] test-network: add tests for vlan QoS mapping
+
+---
+ .../conf/21-vlan.netdev.d/override.conf | 10 ++++++----
+ test/test-network/systemd-networkd-tests.py | 14 ++++++++------
+ 2 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/test/test-network/conf/21-vlan.netdev.d/override.conf b/test/test-network/conf/21-vlan.netdev.d/override.conf
+index 3b8d47d9b1db5..c71077d274a69 100644
+--- a/test/test-network/conf/21-vlan.netdev.d/override.conf
++++ b/test/test-network/conf/21-vlan.netdev.d/override.conf
+@@ -3,7 +3,9 @@ MTUBytes=2000
+
+ [VLAN]
+ Id=99
+-GVRP=true
+-MVRP=true
+-LooseBinding=true
+-ReorderHeader=true
++GVRP=yes
++MVRP=yes
++LooseBinding=yes
++ReorderHeader=yes
++EgressQOSMaps=0-1 1-3 10-3 6-6 7-7
++IngressQOSMaps=15-13 20-100
+diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
+index fe72f37ce4f47..8b01718d55e64 100755
+--- a/test/test-network/systemd-networkd-tests.py
++++ b/test/test-network/systemd-networkd-tests.py
+@@ -1285,12 +1285,14 @@ def test_vlan(self):
+
+ output = check_output('ip -d link show vlan99')
+ print(output)
+- self.assertRegex(output, ' mtu 2000 ')
+- self.assertRegex(output, 'REORDER_HDR')
+- self.assertRegex(output, 'LOOSE_BINDING')
+- self.assertRegex(output, 'GVRP')
+- self.assertRegex(output, 'MVRP')
+- self.assertRegex(output, ' id 99 ')
++ self.assertIn(' mtu 2000 ', output)
++ self.assertIn('REORDER_HDR', output)
++ self.assertIn('LOOSE_BINDING', output)
++ self.assertIn('GVRP', output)
++ self.assertIn('MVRP', output)
++ self.assertIn(' id 99 ', output)
++ self.assertIn('ingress-qos-map { 4:100 7:13 }', output)
++ self.assertIn('egress-qos-map { 0:1 1:3 6:6 7:7 10:3 }', output)
+
+ output = check_output('ip -4 address show dev test1')
+ print(output)
diff --git a/meta/recipes-core/systemd/systemd_250.5.bb b/meta/recipes-core/systemd/systemd_250.5.bb
index 80a797cf2c..4d520c85f3 100644
--- a/meta/recipes-core/systemd/systemd_250.5.bb
+++ b/meta/recipes-core/systemd/systemd_250.5.bb
@@ -33,6 +33,7 @@ SRC_URI += "file://touchscreen.rules \
file://0001-network-remove-only-managed-configs-on-reconfigure-o.patch \
file://0001-nspawn-make-sure-host-root-can-write-to-the-uidmappe.patch \
file://CVE-2023-7008.patch \
+ file://fix-vlan-qos-mapping.patch \
"
# patches needed by musl
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
index 768961de2c..95fb572362 100644
--- a/meta/recipes-devtools/go/go-1.17.13.inc
+++ b/meta/recipes-devtools/go/go-1.17.13.inc
@@ -55,6 +55,7 @@ SRC_URI += "\
file://CVE-2023-45290.patch \
file://CVE-2024-24784.patch \
file://CVE-2024-24785.patch \
+ file://CVE-2023-45288.patch \
"
SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2023-45288.patch b/meta/recipes-devtools/go/go-1.18/CVE-2023-45288.patch
new file mode 100644
index 0000000000..741e7be89a
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2023-45288.patch
@@ -0,0 +1,95 @@
+From e55d7cf8435ba4e58d4a5694e63b391821d4ee9b Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Thu, 28 Mar 2024 16:57:51 -0700
+Subject: [PATCH] [release-branch.go1.22] net/http: update bundled
+ golang.org/x/net/http2
+
+Disable cmd/internal/moddeps test, since this update includes PRIVATE
+track fixes.
+
+Fixes CVE-2023-45288
+For #65051
+Fixes #66298
+
+Change-Id: I5bbf774ebe7651e4bb7e55139d3794bd2b8e8fa8
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2197227
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/576076
+Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
+TryBot-Bypass: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Than McIntosh <thanm@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/e55d7cf8435ba4e58d4a5694e63b391821d4ee9b]
+CVE: CVE-2023-45288
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/cmd/internal/moddeps/moddeps_test.go | 1 +
+ src/net/http/h2_bundle.go | 31 ++++++++++++++++++++++++
+ 2 files changed, 32 insertions(+)
+
+diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go
+index d48d43f..250bde4 100644
+--- a/src/cmd/internal/moddeps/moddeps_test.go
++++ b/src/cmd/internal/moddeps/moddeps_test.go
+@@ -34,6 +34,7 @@ import (
+ // See issues 36852, 41409, and 43687.
+ // (Also see golang.org/issue/27348.)
+ func TestAllDependencies(t *testing.T) {
++ t.Skip("TODO(#65051): 1.22.2 contains unreleased changes from vendored modules")
+ t.Skip("TODO(#57009): 1.19.4 contains unreleased changes from vendored modules")
+ t.Skip("TODO(#53977): 1.18.5 contains unreleased changes from vendored modules")
+
+diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
+index 9d6abd8..10ff193 100644
+--- a/src/net/http/h2_bundle.go
++++ b/src/net/http/h2_bundle.go
+@@ -2842,6 +2842,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
+ if size > remainSize {
+ hdec.SetEmitEnabled(false)
+ mh.Truncated = true
++ remainSize = 0
+ return
+ }
+ remainSize -= size
+@@ -2854,6 +2855,36 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
+ var hc http2headersOrContinuation = hf
+ for {
+ frag := hc.HeaderBlockFragment()
++
++ // Avoid parsing large amounts of headers that we will then discard.
++ // If the sender exceeds the max header list size by too much,
++ // skip parsing the fragment and close the connection.
++ //
++ // "Too much" is either any CONTINUATION frame after we've already
++ // exceeded the max header list size (in which case remainSize is 0),
++ // or a frame whose encoded size is more than twice the remaining
++ // header list bytes we're willing to accept.
++ if int64(len(frag)) > int64(2*remainSize) {
++ if http2VerboseLogs {
++ log.Printf("http2: header list too large")
++ }
++ // It would be nice to send a RST_STREAM before sending the GOAWAY,
++ // but the struture of the server's frame writer makes this difficult.
++ return nil, http2ConnectionError(http2ErrCodeProtocol)
++ }
++
++ // Also close the connection after any CONTINUATION frame following an
++ // invalid header, since we stop tracking the size of the headers after
++ // an invalid one.
++ if invalid != nil {
++ if http2VerboseLogs {
++ log.Printf("http2: invalid header: %v", invalid)
++ }
++ // It would be nice to send a RST_STREAM before sending the GOAWAY,
++ // but the struture of the server's frame writer makes this difficult.
++ return nil, http2ConnectionError(http2ErrCodeProtocol)
++ }
++
+ if _, err := hdec.Write(frag); err != nil {
+ return nil, http2ConnectionError(http2ErrCodeCompression)
+ }
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2024-27281.patch b/meta/recipes-devtools/ruby/ruby/CVE-2024-27281.patch
new file mode 100644
index 0000000000..6f4b35a786
--- /dev/null
+++ b/meta/recipes-devtools/ruby/ruby/CVE-2024-27281.patch
@@ -0,0 +1,97 @@
+From da7a0c7553ef7250ca665a3fecdc01dbaacbb43d Mon Sep 17 00:00:00 2001
+From: Nobuyoshi Nakada <nobu@ruby-lang.org>
+Date: Mon, 15 Apr 2024 11:40:00 +0000
+Subject: [PATCH] Filter marshaled objets
+
+CVE: CVE-2024-27281
+Upstream-Status: Backport [https://github.com/ruby/rdoc/commit/da7a0c7553ef7250ca665a3fecdc01dbaacbb43d]
+
+Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
+---
+ lib/rdoc/store.rb | 45 ++++++++++++++++++++++++++-------------------
+ 1 file changed, 26 insertions(+), 19 deletions(-)
+
+diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
+index 5ba671c..c793e49 100644
+--- a/lib/rdoc/store.rb
++++ b/lib/rdoc/store.rb
+@@ -556,9 +556,7 @@ class RDoc::Store
+ def load_cache
+ #orig_enc = @encoding
+
+- File.open cache_path, 'rb' do |io|
+- @cache = Marshal.load io.read
+- end
++ @cache = marshal_load(cache_path)
+
+ load_enc = @cache[:encoding]
+
+@@ -615,9 +613,7 @@ class RDoc::Store
+ def load_class_data klass_name
+ file = class_file klass_name
+
+- File.open file, 'rb' do |io|
+- Marshal.load io.read
+- end
++ marshal_load(file)
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, klass_name)
+ error.set_backtrace e.backtrace
+@@ -630,14 +626,10 @@ class RDoc::Store
+ def load_method klass_name, method_name
+ file = method_file klass_name, method_name
+
+- File.open file, 'rb' do |io|
+- obj = Marshal.load io.read
+- obj.store = self
+- obj.parent =
+- find_class_or_module(klass_name) || load_class(klass_name) unless
+- obj.parent
+- obj
+- end
++ obj = marshal_load(file)
++ obj.store = self
++ obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name)
++ obj
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, klass_name + method_name)
+ error.set_backtrace e.backtrace
+@@ -650,11 +642,9 @@ class RDoc::Store
+ def load_page page_name
+ file = page_file page_name
+
+- File.open file, 'rb' do |io|
+- obj = Marshal.load io.read
+- obj.store = self
+- obj
+- end
++ obj = marshal_load(file)
++ obj.store = self
++ obj
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, page_name)
+ error.set_backtrace e.backtrace
+@@ -976,4 +966,21 @@ class RDoc::Store
+ @unique_modules
+ end
+
++ private
++ def marshal_load(file)
++ File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)}
++ end
++
++ MarshalFilter = proc do |obj|
++ case obj
++ when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text
++ else
++ unless obj.class.name.start_with?("RDoc::")
++ raise TypeError, "not permitted class: #{obj.class.name}"
++ end
++ end
++ obj
++ end
++ private_constant :MarshalFilter
++
+ end
+--
+2.35.5
diff --git a/meta/recipes-devtools/ruby/ruby_3.1.3.bb b/meta/recipes-devtools/ruby/ruby_3.1.3.bb
index 228a2204db..2ad3c9e207 100644
--- a/meta/recipes-devtools/ruby/ruby_3.1.3.bb
+++ b/meta/recipes-devtools/ruby/ruby_3.1.3.bb
@@ -33,6 +33,7 @@ SRC_URI = "http://cache.ruby-lang.org/pub/ruby/${SHRT_VER}/ruby-${PV}.tar.gz \
file://CVE-2023-28755.patch \
file://CVE-2023-36617_1.patch \
file://CVE-2023-36617_2.patch \
+ file://CVE-2024-27281.patch \
"
UPSTREAM_CHECK_URI = "https://www.ruby-lang.org/en/downloads/"
diff --git a/meta/recipes-devtools/rust/rust-source.inc b/meta/recipes-devtools/rust/rust-source.inc
index ea70ad786f..c377a680a7 100644
--- a/meta/recipes-devtools/rust/rust-source.inc
+++ b/meta/recipes-devtools/rust/rust-source.inc
@@ -5,3 +5,6 @@ RUSTSRC = "${WORKDIR}/rustc-${PV}-src"
UPSTREAM_CHECK_URI = "https://forge.rust-lang.org/infra/other-installation-methods.html"
UPSTREAM_CHECK_REGEX = "rustc-(?P<pver>\d+(\.\d+)+)-src"
+
+#CVE-2024-24576 is specific to Microsoft Windows
+CVE_CHECK_IGNORE += "CVE-2024-24576"
diff --git a/meta/recipes-devtools/tcltk/tcl/run-ptest b/meta/recipes-devtools/tcltk/tcl/run-ptest
index 51e1e4aa7b..87e025fce1 100644
--- a/meta/recipes-devtools/tcltk/tcl/run-ptest
+++ b/meta/recipes-devtools/tcltk/tcl/run-ptest
@@ -5,8 +5,8 @@ export TZ="Europe/London"
export TCL_LIBRARY=library
# Some tests are overly strict with timings and fail on loaded systems.
-# See bugs #14825 #14882 #15081.
-SKIPPED_TESTS='cmdMZ-6.6 exit-1.* socket-* socket_inet-*'
+# See bugs #14825 #14882 #15081 #15321.
+SKIPPED_TESTS='async-* cmdMZ-6.6 event-* exit-1.* socket-* socket_inet-*'
for i in `ls tests/*.test | awk -F/ '{print $2}'`; do
./tcltest tests/all.tcl -file $i -skip "$SKIPPED_TESTS" >$i.log 2>&1
diff --git a/meta/recipes-devtools/valgrind/valgrind/remove-for-all b/meta/recipes-devtools/valgrind/valgrind/remove-for-all
index cb8d10b18f..226f97b50e 100644
--- a/meta/recipes-devtools/valgrind/valgrind/remove-for-all
+++ b/meta/recipes-devtools/valgrind/valgrind/remove-for-all
@@ -1,8 +1,10 @@
none/tests/amd64/fb_test_amd64
gdbserver_tests/hginfo
+memcheck/tests/linux/timerfd-syscall
memcheck/tests/supp_unknown
helgrind/tests/tls_threads
drd/tests/bar_bad_xml
drd/tests/pth_barrier_thr_cr
drd/tests/thread_name_xml
massif/tests/deep-D
+
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2024-28834.patch b/meta/recipes-support/gnutls/gnutls/CVE-2024-28834.patch
new file mode 100644
index 0000000000..6c06fc2782
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2024-28834.patch
@@ -0,0 +1,457 @@
+From 1c4701ffc342259fc5965d5a0de90d87f780e3e5 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Fri, 12 Jan 2024 17:56:58 +0900
+Subject: [PATCH] nettle: avoid normalization of mpz_t in deterministic ECDSA
+
+This removes function calls that potentially leak bit-length of a
+private key used to calculate a nonce in deterministic ECDSA. Namely:
+
+- _gnutls_dsa_compute_k has been rewritten to work on always
+ zero-padded mp_limb_t arrays instead of mpz_t
+- rnd_mpz_func has been replaced with rnd_datum_func, which is backed
+ by a byte array instead of an mpz_t value
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+
+CVE: CVE-2024-28834
+
+Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/1c4701ffc342259fc5965d5a0de90d87f780e3e5]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ lib/nettle/int/dsa-compute-k.c | 86 ++++++++++++++++++++-----------
+ lib/nettle/int/dsa-compute-k.h | 32 +++++++++---
+ lib/nettle/int/ecdsa-compute-k.c | 32 +++---------
+ lib/nettle/int/ecdsa-compute-k.h | 8 +--
+ lib/nettle/pk.c | 78 +++++++++++++++++++---------
+ tests/sign-verify-deterministic.c | 2 +-
+ 6 files changed, 141 insertions(+), 97 deletions(-)
+
+diff --git a/lib/nettle/int/dsa-compute-k.c b/lib/nettle/int/dsa-compute-k.c
+index 3f5105a..f937693 100644
+--- a/lib/nettle/int/dsa-compute-k.c
++++ b/lib/nettle/int/dsa-compute-k.c
+@@ -31,33 +31,39 @@
+ #include "mpn-base256.h"
+ #include <string.h>
+
+-#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
+-
+-/* The maximum size of q, chosen from the fact that we support
+- * 521-bit elliptic curve generator and 512-bit DSA subgroup at
+- * maximum. */
+-#define MAX_Q_BITS 521
+-#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8)
+-#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS)
+-
+-#define MAX_HASH_BITS (MAX_HASH_SIZE * 8)
+-#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS)
+-
+-int
+-_gnutls_dsa_compute_k(mpz_t k,
+- const mpz_t q,
+- const mpz_t x,
+- gnutls_mac_algorithm_t mac,
+- const uint8_t *digest,
+- size_t length)
++/* For mini-gmp */
++#ifndef GMP_LIMB_BITS
++#define GMP_LIMB_BITS GMP_NUMB_BITS
++#endif
++
++static inline int is_zero_limb(mp_limb_t x)
++{
++ x |= (x << 1);
++ return ((x >> 1) - 1) >> (GMP_LIMB_BITS - 1);
++}
++
++static int sec_zero_p(const mp_limb_t *ap, mp_size_t n)
++{
++ volatile mp_limb_t w;
++ mp_size_t i;
++
++ for (i = 0, w = 0; i < n; i++)
++ w |= ap[i];
++
++
++ return is_zero_limb(w);
++}
++
++int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x,
++ mp_size_t qn, mp_bitcnt_t q_bits,
++ gnutls_mac_algorithm_t mac,
++ const uint8_t *digest,
++ size_t length)
+ {
+ uint8_t V[MAX_HASH_SIZE];
+ uint8_t K[MAX_HASH_SIZE];
+ uint8_t xp[MAX_Q_SIZE];
+ uint8_t tp[MAX_Q_SIZE];
+- mp_limb_t h[MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)];
+- mp_bitcnt_t q_bits = mpz_sizeinbase (q, 2);
+- mp_size_t qn = mpz_size(q);
+ mp_bitcnt_t h_bits = length * 8;
+ mp_size_t hn = BITS_TO_LIMBS(h_bits);
+ size_t nbytes = (q_bits + 7) / 8;
+@@ -66,6 +72,7 @@ _gnutls_dsa_compute_k(mpz_t k,
+ mp_limb_t cy;
+ gnutls_hmac_hd_t hd;
+ int ret = 0;
++ mp_limb_t scratch[MAX_Q_LIMBS];
+
+ if (unlikely(q_bits > MAX_Q_BITS))
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+@@ -73,7 +80,7 @@ _gnutls_dsa_compute_k(mpz_t k,
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ /* int2octets(x) */
+- mpn_get_base256(xp, nbytes, mpz_limbs_read(x), qn);
++ mpn_get_base256(xp, nbytes, x, qn);
+
+ /* bits2octets(h) */
+ mpn_set_base256(h, hn, digest, length);
+@@ -97,12 +104,12 @@ _gnutls_dsa_compute_k(mpz_t k,
+ mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS);
+ }
+
+- cy = mpn_sub_n(h, h, mpz_limbs_read(q), qn);
++ cy = mpn_sub_n(h, h, q, qn);
+ /* Fall back to addmul_1, if nettle is linked with mini-gmp. */
+ #ifdef mpn_cnd_add_n
+- mpn_cnd_add_n(cy, h, h, mpz_limbs_read(q), qn);
++ mpn_cnd_add_n(cy, h, h, q, qn);
+ #else
+- mpn_addmul_1(h, mpz_limbs_read(q), qn, cy != 0);
++ mpn_addmul_1(h, q, qn, cy != 0);
+ #endif
+ mpn_get_base256(tp, nbytes, h, qn);
+
+@@ -178,12 +185,8 @@ _gnutls_dsa_compute_k(mpz_t k,
+ if (tlen * 8 > q_bits)
+ mpn_rshift (h, h, qn, tlen * 8 - q_bits);
+ /* Check if k is in [1,q-1] */
+- if (!mpn_zero_p (h, qn) &&
+- mpn_cmp (h, mpz_limbs_read(q), qn) < 0) {
+- mpn_copyi(mpz_limbs_write(k, qn), h, qn);
+- mpz_limbs_finish(k, qn);
++ if (!sec_zero_p(h, qn) && mpn_sub_n(scratch, h, q, qn))
+ break;
+- }
+
+ ret = gnutls_hmac_init(&hd, mac, K, length);
+ if (ret < 0)
+@@ -207,3 +210,24 @@ _gnutls_dsa_compute_k(mpz_t k,
+
+ return ret;
+ }
++
++/* cancel-out dsa_sign's addition of 1 to random data */
++void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
++ mp_size_t n)
++{
++ /* Fall back to sub_1, if nettle is linked with mini-gmp. */
++#ifdef mpn_sec_sub_1
++ mp_limb_t t[MAX_Q_LIMBS];
++
++ mpn_sec_sub_1(h, h, n, 1, t);
++#else
++ mpn_sub_1(h, h, n, 1);
++#endif
++ mpn_get_base256(k, nbytes, h, n);
++}
++
++void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
++ mp_size_t n)
++{
++ mpn_get_base256(k, nbytes, h, n);
++}
+diff --git a/lib/nettle/int/dsa-compute-k.h b/lib/nettle/int/dsa-compute-k.h
+index 64e90e0..778c484 100644
+--- a/lib/nettle/int/dsa-compute-k.h
++++ b/lib/nettle/int/dsa-compute-k.h
+@@ -26,12 +26,30 @@
+ #include <gnutls/gnutls.h>
+ #include <nettle/bignum.h> /* includes gmp.h */
+
+-int
+-_gnutls_dsa_compute_k(mpz_t k,
+- const mpz_t q,
+- const mpz_t x,
+- gnutls_mac_algorithm_t mac,
+- const uint8_t *digest,
+- size_t length);
++#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
++
++/* The maximum size of q, chosen from the fact that we support
++ * 521-bit elliptic curve generator and 512-bit DSA subgroup at
++ * maximum. */
++#define MAX_Q_BITS 521
++#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8)
++#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS)
++
++#define MAX_HASH_BITS (MAX_HASH_SIZE * 8)
++#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS)
++
++#define DSA_COMPUTE_K_ITCH MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)
++
++int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x,
++ mp_size_t qn, mp_bitcnt_t q_bits,
++ gnutls_mac_algorithm_t mac,
++ const uint8_t *digest,
++ size_t length);
++
++void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
++ mp_size_t n);
++
++void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h,
++ mp_size_t n);
+
+ #endif /* GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H */
+diff --git a/lib/nettle/int/ecdsa-compute-k.c b/lib/nettle/int/ecdsa-compute-k.c
+index 94914eb..fc3b2ba 100644
+--- a/lib/nettle/int/ecdsa-compute-k.c
++++ b/lib/nettle/int/ecdsa-compute-k.c
+@@ -29,39 +29,38 @@
+ #include "dsa-compute-k.h"
+ #include "gnutls_int.h"
+
+-static inline int
+-_gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve)
++int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve)
+ {
+ switch (curve) {
+ #ifdef ENABLE_NON_SUITEB_CURVES
+ case GNUTLS_ECC_CURVE_SECP192R1:
+- mpz_init_set_str(*q,
++ mpz_init_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836"
+ "146BC9B1B4D22831",
+ 16);
+ return 0;
+ case GNUTLS_ECC_CURVE_SECP224R1:
+- mpz_init_set_str(*q,
++ mpz_init_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2"
+ "E0B8F03E13DD29455C5C2A3D",
+ 16);
+ return 0;
+ #endif
+ case GNUTLS_ECC_CURVE_SECP256R1:
+- mpz_init_set_str(*q,
++ mpz_init_set_str(q,
+ "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
+ "BCE6FAADA7179E84F3B9CAC2FC632551",
+ 16);
+ return 0;
+ case GNUTLS_ECC_CURVE_SECP384R1:
+- mpz_init_set_str(*q,
++ mpz_init_set_str(q,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
+ "581A0DB248B0A77AECEC196ACCC52973",
+ 16);
+ return 0;
+ case GNUTLS_ECC_CURVE_SECP521R1:
+- mpz_init_set_str(*q,
++ mpz_init_set_str(q,
+ "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFA51868783BF2F966B7FCC0148F709A"
+@@ -74,22 +73,3 @@ _gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve)
+ }
+ }
+
+-int
+-_gnutls_ecdsa_compute_k (mpz_t k,
+- gnutls_ecc_curve_t curve,
+- const mpz_t x,
+- gnutls_mac_algorithm_t mac,
+- const uint8_t *digest,
+- size_t length)
+-{
+- mpz_t q;
+- int ret;
+-
+- ret = _gnutls_ecc_curve_to_dsa_q(&q, curve);
+- if (ret < 0)
+- return gnutls_assert_val(ret);
+-
+- ret = _gnutls_dsa_compute_k (k, q, x, mac, digest, length);
+- mpz_clear(q);
+- return ret;
+-}
+diff --git a/lib/nettle/int/ecdsa-compute-k.h b/lib/nettle/int/ecdsa-compute-k.h
+index 7ca401d..a7e612b 100644
+--- a/lib/nettle/int/ecdsa-compute-k.h
++++ b/lib/nettle/int/ecdsa-compute-k.h
+@@ -26,12 +26,6 @@
+ #include <gnutls/gnutls.h>
+ #include <nettle/bignum.h> /* includes gmp.h */
+
+-int
+-_gnutls_ecdsa_compute_k (mpz_t k,
+- gnutls_ecc_curve_t curve,
+- const mpz_t x,
+- gnutls_mac_algorithm_t mac,
+- const uint8_t *digest,
+- size_t length);
++int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve);
+
+ #endif /* GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H */
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index eba246f..799cc9d 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -97,10 +97,16 @@ static void rnd_nonce_func(void *_ctx, size_t length, uint8_t * data)
+ }
+ }
+
+-static void rnd_mpz_func(void *_ctx, size_t length, uint8_t * data)
++static void rnd_datum_func(void *ctx, size_t length, uint8_t *data)
+ {
+- mpz_t *k = _ctx;
+- nettle_mpz_get_str_256 (length, data, *k);
++ gnutls_datum_t *d = ctx;
++
++ if (length > d->size) {
++ memset(data, 0, length - d->size);
++ memcpy(data + (length - d->size), d->data, d->size);
++ } else {
++ memcpy(data, d->data, length);
++ }
+ }
+
+ static void rnd_nonce_func_fallback(void *_ctx, size_t length, uint8_t * data)
+@@ -1076,7 +1082,11 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ struct dsa_signature sig;
+ int curve_id = pk_params->curve;
+ const struct ecc_curve *curve;
+- mpz_t k;
++ mpz_t q;
++ /* 521-bit elliptic curve generator at maximum */
++ uint8_t buf[(521 + 7) / 8];
++ gnutls_datum_t k = { NULL, 0 };
++
+ void *random_ctx;
+ nettle_random_func *random_func;
+
+@@ -1123,19 +1133,31 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ hash_len = vdata->size;
+ }
+
+- mpz_init(k);
++ mpz_init(q);
++
+ if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
+ (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+- ret = _gnutls_ecdsa_compute_k(k,
+- curve_id,
+- pk_params->params[ECC_K],
+- DIG_TO_MAC(sign_params->dsa_dig),
+- vdata->data,
+- vdata->size);
++ mp_limb_t h[DSA_COMPUTE_K_ITCH];
++
++ ret = _gnutls_ecc_curve_to_dsa_q(q, curve_id);
+ if (ret < 0)
+ goto ecdsa_cleanup;
++
++ ret = _gnutls_dsa_compute_k(
++ h, mpz_limbs_read(q), priv.p,
++ ecc_size(priv.ecc), ecc_bit_size(priv.ecc),
++ DIG_TO_MAC(sign_params->dsa_dig), vdata->data,
++ vdata->size);
++ if (ret < 0)
++ goto ecdsa_cleanup;
++ k.data = buf;
++ k.size = (ecc_bit_size(priv.ecc) + 7) / 8;
++
++ _gnutls_ecdsa_compute_k_finish(k.data, k.size, h,
++ ecc_size(priv.ecc));
++
+ random_ctx = &k;
+- random_func = rnd_mpz_func;
++ random_func = rnd_datum_func;
+ } else {
+ random_ctx = NULL;
+ random_func = rnd_nonce_func;
+@@ -1156,7 +1178,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ ecdsa_cleanup:
+ dsa_signature_clear(&sig);
+ ecc_scalar_zclear(&priv);
+- mpz_clear(k);
++ mpz_clear(q);
+
+ if (ret < 0) {
+ gnutls_assert();
+@@ -1169,7 +1191,10 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ struct dsa_params pub;
+ bigint_t priv;
+ struct dsa_signature sig;
+- mpz_t k;
++ /* 512-bit DSA subgroup at maximum */
++ uint8_t buf[(512 + 7) / 8];
++ gnutls_datum_t k = { NULL, 0 };
++
+ void *random_ctx;
+ nettle_random_func *random_func;
+
+@@ -1196,21 +1221,25 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ hash_len = vdata->size;
+ }
+
+- mpz_init(k);
+ if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
+ (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+- ret = _gnutls_dsa_compute_k(k,
+- pub.q,
+- TOMPZ(priv),
+- DIG_TO_MAC(sign_params->dsa_dig),
+- vdata->data,
+- vdata->size);
++ mp_limb_t h[DSA_COMPUTE_K_ITCH];
++ ret = _gnutls_dsa_compute_k(
++ h, mpz_limbs_read(pub.q),
++ mpz_limbs_read(TOMPZ(priv)), mpz_size(pub.q),
++ mpz_sizeinbase(pub.q, 2),
++ DIG_TO_MAC(sign_params->dsa_dig), vdata->data,
++ vdata->size);
+ if (ret < 0)
+ goto dsa_fail;
+- /* cancel-out dsa_sign's addition of 1 to random data */
+- mpz_sub_ui (k, k, 1);
++ k.data = buf;
++ k.size = (mpz_sizeinbase(pub.q, 2) + 7) / 8;
++
++ _gnutls_dsa_compute_k_finish(k.data, k.size, h,
++ mpz_size(pub.q));
++
+ random_ctx = &k;
+- random_func = rnd_mpz_func;
++ random_func = rnd_datum_func;
+ } else {
+ random_ctx = NULL;
+ random_func = rnd_nonce_func;
+@@ -1230,7 +1259,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+
+ dsa_fail:
+ dsa_signature_clear(&sig);
+- mpz_clear(k);
+
+ if (ret < 0) {
+ gnutls_assert();
+diff --git a/tests/sign-verify-deterministic.c b/tests/sign-verify-deterministic.c
+index 6e90728..25aa553 100644
+--- a/tests/sign-verify-deterministic.c
++++ b/tests/sign-verify-deterministic.c
+@@ -197,7 +197,7 @@ void doit(void)
+ &signature);
+ if (ret < 0)
+ testfail("gnutls_pubkey_verify_data2\n");
+- success(" - pass");
++ success(" - pass\n");
+
+ next:
+ gnutls_free(signature.data);
+--
+2.40.0
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2024-28835.patch b/meta/recipes-support/gnutls/gnutls/CVE-2024-28835.patch
new file mode 100644
index 0000000000..0341df8bd9
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2024-28835.patch
@@ -0,0 +1,406 @@
+From e369e67a62f44561d417cb233acc566cc696d82d Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <ueno@gnu.org>
+Date: Mon, 29 Jan 2024 13:52:46 +0900
+Subject: [PATCH] gnutls_x509_trust_list_verify_crt2: remove length limit of
+ input
+
+Previously, if cert_list_size exceeded DEFAULT_MAX_VERIFY_DEPTH, the
+chain verification logic crashed with assertion failure. This patch
+removes the restriction while keeping the maximum number of
+retrieved certificates being DEFAULT_MAX_VERIFY_DEPTH.
+
+Signed-off-by: Daiki Ueno <ueno@gnu.org>
+
+CVE: CVE-2024-28835
+
+Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/e369e67a62f44561d417cb233acc566cc696d82d]
+
+Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
+---
+ lib/gnutls_int.h | 5 +-
+ lib/x509/common.c | 10 +-
+ lib/x509/verify-high.c | 43 ++++++---
+ tests/test-chains.h | 211 ++++++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 252 insertions(+), 17 deletions(-)
+
+diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
+index b2a3ae6..5127996 100644
+--- a/lib/gnutls_int.h
++++ b/lib/gnutls_int.h
+@@ -221,7 +221,10 @@ typedef enum record_send_state_t {
+
+ #define MAX_PK_PARAM_SIZE 2048
+
+-/* defaults for verification functions
++/* Defaults for verification functions.
++ *
++ * update many_icas in tests/test-chains.h when increasing
++ * DEFAULT_MAX_VERIFY_DEPTH.
+ */
+ #define DEFAULT_MAX_VERIFY_DEPTH 16
+ #define DEFAULT_MAX_VERIFY_BITS (MAX_PK_PARAM_SIZE*8)
+diff --git a/lib/x509/common.c b/lib/x509/common.c
+index 6367b03..8f8c1f8 100644
+--- a/lib/x509/common.c
++++ b/lib/x509/common.c
+@@ -1749,7 +1749,15 @@ unsigned int _gnutls_sort_clist(gnutls_x509_crt_t *clist,
+ bool insorted[DEFAULT_MAX_VERIFY_DEPTH]; /* non zero if clist[i] used in sorted list */
+ gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
+
+- assert(clist_size <= DEFAULT_MAX_VERIFY_DEPTH);
++ /* Limit the number of certificates in the chain, to avoid DoS
++ * because of the O(n^2) sorting below. FIXME: Switch to a
++ * topological sort algorithm which should be linear to the
++ * number of certificates and subject-issuer relationships.
++ */
++ if (clist_size > DEFAULT_MAX_VERIFY_DEPTH) {
++ _gnutls_debug_log("too many certificates; skipping sorting\n");
++ return 1;
++ }
+
+ for (i = 0; i < DEFAULT_MAX_VERIFY_DEPTH; i++) {
+ issuer[i] = -1;
+diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c
+index 5698d4f..a957511 100644
+--- a/lib/x509/verify-high.c
++++ b/lib/x509/verify-high.c
+@@ -25,7 +25,7 @@
+ #include "errors.h"
+ #include <libtasn1.h>
+ #include <global.h>
+-#include <num.h> /* MAX */
++#include <num.h> /* MIN */
+ #include <tls-sig.h>
+ #include <str.h>
+ #include <datum.h>
+@@ -1418,7 +1418,8 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ int ret = 0;
+ unsigned int i;
+ size_t hash;
+- gnutls_x509_crt_t sorted[DEFAULT_MAX_VERIFY_DEPTH];
++ gnutls_x509_crt_t *cert_list_copy = NULL;
++ unsigned int cert_list_max_size = 0;
+ gnutls_x509_crt_t retrieved[DEFAULT_MAX_VERIFY_DEPTH];
+ unsigned int retrieved_size = 0;
+ const char *hostname = NULL, *purpose = NULL, *email = NULL;
+@@ -1472,16 +1473,26 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ }
+ }
+
+- memcpy(sorted, cert_list, cert_list_size * sizeof(gnutls_x509_crt_t));
+- cert_list = sorted;
++ /* Allocate extra for retrieved certificates. */
++ if (!INT_ADD_OK(cert_list_size, DEFAULT_MAX_VERIFY_DEPTH,
++ &cert_list_max_size))
++ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++ cert_list_copy = _gnutls_reallocarray(NULL, cert_list_max_size,
++ sizeof(gnutls_x509_crt_t));
++ if (!cert_list_copy)
++ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
++
++ memcpy(cert_list_copy, cert_list,
++ cert_list_size * sizeof(gnutls_x509_crt_t));
++ cert_list = cert_list_copy;
+
+ ret = cert_set_init(&cert_set, DEFAULT_MAX_VERIFY_DEPTH);
+ if (ret < 0) {
+ return ret;
+ }
+
+- for (i = 0; i < cert_list_size &&
+- cert_list_size <= DEFAULT_MAX_VERIFY_DEPTH; ) {
++ for (i = 0; i < cert_list_size;) {
+ unsigned int sorted_size = 1;
+ unsigned int j;
+ gnutls_x509_crt_t issuer;
+@@ -1491,8 +1502,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ cert_list_size - i);
+ }
+
+- /* Remove duplicates. Start with index 1, as the first element
+- * may be re-checked after issuer retrieval. */
++ /* Remove duplicates. */
+ for (j = 1; j < sorted_size; j++) {
+ if (cert_set_contains(&cert_set, cert_list[i + j])) {
+ if (i + j < cert_list_size - 1) {
+@@ -1539,14 +1549,16 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ ret = retrieve_issuers(list,
+ cert_list[i - 1],
+ &retrieved[retrieved_size],
+- DEFAULT_MAX_VERIFY_DEPTH -
+- MAX(retrieved_size,
+- cert_list_size));
++ MIN(DEFAULT_MAX_VERIFY_DEPTH - retrieved_size,
++ cert_list_max_size - cert_list_size));
+ if (ret < 0) {
+ break;
+ } else if (ret > 0) {
+ assert((unsigned int)ret <=
+- DEFAULT_MAX_VERIFY_DEPTH - cert_list_size);
++ DEFAULT_MAX_VERIFY_DEPTH - retrieved_size);
++ assert((unsigned int)ret <=
++ cert_list_max_size - cert_list_size);
++
+ memmove(&cert_list[i + ret],
+ &cert_list[i],
+ (cert_list_size - i) *
+@@ -1563,8 +1575,10 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ }
+
+ cert_list_size = shorten_clist(list, cert_list, cert_list_size);
+- if (cert_list_size <= 0)
+- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
++ if (cert_list_size <= 0) {
++ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
++ goto cleanup;
++ }
+
+ hash =
+ hash_pjw_bare(cert_list[cert_list_size - 1]->raw_issuer_dn.
+@@ -1715,6 +1729,7 @@ gnutls_x509_trust_list_verify_crt2(gnutls_x509_trust_list_t list,
+ }
+
+ cleanup:
++ gnutls_free(cert_list_copy);
+ for (i = 0; i < retrieved_size; i++) {
+ gnutls_x509_crt_deinit(retrieved[i]);
+ }
+diff --git a/tests/test-chains.h b/tests/test-chains.h
+index 09a5461..dd872a9 100644
+--- a/tests/test-chains.h
++++ b/tests/test-chains.h
+@@ -25,7 +25,7 @@
+
+ /* *INDENT-OFF* */
+
+-#define MAX_CHAIN 10
++#define MAX_CHAIN 17
+
+ static const char *chain_with_no_subject_id_in_ca_ok[] = {
+ "-----BEGIN CERTIFICATE-----\n"
+@@ -4386,6 +4386,213 @@ static const char *cross_signed_ca[] = {
+ NULL
+ };
+
++/* This assumes DEFAULT_MAX_VERIFY_DEPTH to be 16 */
++static const char *many_icas[] = {
++ /* Server */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBqzCCAV2gAwIBAgIUIK3+SD3GmqJlRLZ/ESyhTzkSDL8wBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowNzEbMBkGA1UEChMSR251VExTIHRlc3Qgc2VydmVyMRgwFgYD\n"
++ "VQQDEw90ZXN0LmdudXRscy5vcmcwKjAFBgMrZXADIQAWGjx45NIJiKFsNBxxRRjm\n"
++ "NxUT5KYK7xXr5HPVywwgLaOBkjCBjzAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGC\n"
++ "D3Rlc3QuZ251dGxzLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATAOBgNVHQ8BAf8E\n"
++ "BAMCB4AwHQYDVR0OBBYEFKgNAQWZPx76/vXqQOdIi5mTftsaMB8GA1UdIwQYMBaA\n"
++ "FDaPsY6WAGuRtrhYJE6Gk/bg5qbdMAUGAytlcANBAMIDh8aGcIIFDTUrzfV7tnkX\n"
++ "hHrxyFKBH/cApf6xcJQTfDXm23po627Ibp+WgLaWMY08Fn9Y2V6Ev8ADfqXNbQ8=\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA16 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUSnE0PKdm/dsnZSWBh5Ct4pS6DcwwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAxq9SI8vp0QH1dDBBuZW+t+bLLROppQbjSQ4O1BEonDOjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ2j7GOlgBrkba4\n"
++ "WCROhpP24Oam3TAfBgNVHSMEGDAWgBRvdUKX0aw3nfUIdvivXGSfRO7zyjAFBgMr\n"
++ "ZXADQQBsI2Hc7X5hXoHTvk01qMc5a1I27QHAFRARJnvIQ15wxNS2LVLzGk+AUmwr\n"
++ "sOhBKAcVfS55uWtYdjoWQ80h238H\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA15 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUQk4XkgQVImnp6OPZas7ctwgBza4wBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAs3yVKLJd3sKbNVmj6Bxy2j1x025rksyQpZZWnCx5a+CjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRvdUKX0aw3nfUI\n"
++ "dvivXGSfRO7zyjAfBgNVHSMEGDAWgBRhGfUXYPh4YQsdtTWYUozLphGgfzAFBgMr\n"
++ "ZXADQQBXTtm56x6/pHXdW8dTvZLc/8RufNQrMlc23TCgX0apUnrZdTsNAb7OE4Uu\n"
++ "9PBuxK+CC9NL/BL2hXsKvAT+NWME\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA14 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUKfwz7UUYRvYlvqwmnLJlTOS9o1AwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAXbUetQ08t+F4+IcKL++HpeclqTxXZ7cG4mwqvHmTUEWjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRhGfUXYPh4YQsd\n"
++ "tTWYUozLphGgfzAfBgNVHSMEGDAWgBQYRQqO+V1kefF7QvNnFU1fX5H9+jAFBgMr\n"
++ "ZXADQQAiSHNMTLPFP3oa6q13Dj8jSxF9trQDJGM1ArWffFcPZUt2U4/ODHdcMTHx\n"
++ "kGwhIj+ghBlu6ykgu6J2wewCUooC\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA13 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUUKOs59gyCPAZzoC7zMZQSh6AnQgwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAmvqhj5GYqsXIpsr1BXBfD+2mTP/m/TEpKIYSZHM62dijYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQYRQqO+V1kefF7\n"
++ "QvNnFU1fX5H9+jAfBgNVHSMEGDAWgBQ27HzvP5hl2xR+LOzRcPfmY5ndXjAFBgMr\n"
++ "ZXADQQBrB3NkrYC7EQ74qgeesVOE71rW012dPOOKPAV0laR+JLEgsv9sfus+AdBF\n"
++ "WBNwR3KeYBTi/MFDuecxBHU2m5gD\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA12 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUUQooGfH21+sR7/pSgCWm13gg2H4wBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAK2of/B4wMpk6k/KdugC5dMS+jo2fseUM7/PvXkE6HASjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ27HzvP5hl2xR+\n"
++ "LOzRcPfmY5ndXjAfBgNVHSMEGDAWgBSJDHU0Mj1Xr0e8ErCnRK24w7XwTTAFBgMr\n"
++ "ZXADQQDY8d2bAZpj7oGhdl2dBsCE48jEWj49da0PbgN12koAj3gf4hjMPd8G7p5z\n"
++ "8RsURAwQmCkE8ShvdNw/Qr2tDL0E\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA11 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUW9Dw0hU2pfjXhb5Stip+mk9SndIwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAn5ISjLVV6RBWsnxDWHDicpye7SjFwGOTwzF01/psiJ2jYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSJDHU0Mj1Xr0e8\n"
++ "ErCnRK24w7XwTTAfBgNVHSMEGDAWgBSR9UU27RI0XohiEgHDxNo/9HP4djAFBgMr\n"
++ "ZXADQQCfQg6MDHk71vhyrEo4/5PcLb2Li5F/FKURyux7snv2TbkSdInloAqca9UR\n"
++ "DtqHSLCNLXCNdSPr5QwIt5p29rsE\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA10 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUR4uTedG8e6MibKViQ3eX7QzXG1swBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAnslX04kSVOL5LAf1e+Ze3ggNnDJcEAxLDk8I/IhyjTyjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSR9UU27RI0Xohi\n"
++ "EgHDxNo/9HP4djAfBgNVHSMEGDAWgBRC7US5gJYnvd5F7EN+C4anMgd2NzAFBgMr\n"
++ "ZXADQQDo+jHt07Tvz3T5Lbz6apBrSln8xKYfJk2W1wP85XAnf7sZT9apM1bS4EyD\n"
++ "Kckw+KG+9x7myOZz6AXJgZB5OGAO\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA9 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUSIIIRjrNpE+kEPkiJMOqaNAazvQwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAZKy7p1Gn4W/reRxKJN99+QkHt2q9aELktCKe5PqrX5ejYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRC7US5gJYnvd5F\n"
++ "7EN+C4anMgd2NzAfBgNVHSMEGDAWgBSOhR7Ornis2x8g0J+bvTTwMnW60zAFBgMr\n"
++ "ZXADQQA0MEcC4FgKZEAfalVpApU2to0G158MVz/WTNcSc7fnl8ifJ/g56dVHL1jr\n"
++ "REvC/S28dn/CGAlbVXUAgxnHAbgE\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA8 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUGGFSgD95vOTSj7iFxfXA5vq6vsYwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAg3W/bTdW0fR32NeZEVMXICpa30d7rSdddLOYDvqqUO+jYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSOhR7Ornis2x8g\n"
++ "0J+bvTTwMnW60zAfBgNVHSMEGDAWgBT3zK8Hbn9aVTAOOFY6RSxJ2o5x2jAFBgMr\n"
++ "ZXADQQBl4gnzE463iMFg57gPvjHdVzA39sJBpiu0kUGfRcLnoRI/VOaLcx7WnJ9+\n"
++ "c3KxPZBec76EdIoQDkTmI6m2FIAM\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA7 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUGktMGXhNuaMhKyAlecymmLD+/GIwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEA/Z1oc76hOQ0Hi+2hePaGIntnMIDqBlb7RDMjRpYONP2jYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBT3zK8Hbn9aVTAO\n"
++ "OFY6RSxJ2o5x2jAfBgNVHSMEGDAWgBSPae3JUN3jP0NgUJqDV3eYxcaM3DAFBgMr\n"
++ "ZXADQQBMkwKaUZlvG/hax8rv3nnDv8kJOr6KVHBnxSx3hZ+8HIBT7GFm1+YDeYOB\n"
++ "jhNg66kyeFPGXXBCe+mvNQFFjCEE\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA6 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUKn3gz5lAUpKqWlHKLKYDbOJ4rygwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAZ/eD4eTe91ddvHusm7YlLPxU4ByGFc6suAmlP1CxXkWjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSPae3JUN3jP0Ng\n"
++ "UJqDV3eYxcaM3DAfBgNVHSMEGDAWgBT9f/qSI/jhxvGI7aMtkpraDcjBnjAFBgMr\n"
++ "ZXADQQAMRnkmRhnLGdmJaY8B42gfyaAsqCMyds/Tw4OHYy+N48XuAxRjKkhf3szC\n"
++ "0lY71oU043mNP1yx/dzAuCTrVSgI\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA5 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUEgEYbBXXEyGv3vOq10JQv1SBiUUwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAs2xEDPw8RVal53nX9GVwUd1blq1wjtVFC8S1V7up7MWjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBT9f/qSI/jhxvGI\n"
++ "7aMtkpraDcjBnjAfBgNVHSMEGDAWgBRBVkLu9BmCKz7HNI8md4vPpoE/7jAFBgMr\n"
++ "ZXADQQCCufAyLijtzzmeCuO3K50rBSbGvB3FQfep7g6kVsQKM3bw/olWK5/Ji0dD\n"
++ "ubJ0cFl1FmfAda7aVxLBtJOvO6MI\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA4 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIULj8GkaHw+92HuOTnXnXlxCy3VrEwBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAiedxh4dvtwDellMAHc/pZH0MAOXobRenTUgF1yj5l12jYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBRBVkLu9BmCKz7H\n"
++ "NI8md4vPpoE/7jAfBgNVHSMEGDAWgBSDtNRgQ36KwW/ASaMyr6WeDt0STDAFBgMr\n"
++ "ZXADQQDL8U2ckzur7CktdrVUNvfLhVCOz33d/62F28vQFHUa8h/4h+Mi1MMbXOKT\n"
++ "1bL2TvpFpU7Fx/vcIPXDielVqr4C\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA3 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUQXl74TDDw6MQRMbQUSPa6Qrvba8wBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEA7l0jQ0f4fJRw7Qja/Hz2qn8y91SI7CokxhSf+FT+9M6jYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSDtNRgQ36KwW/A\n"
++ "SaMyr6WeDt0STDAfBgNVHSMEGDAWgBQ2inEK4KH6ATftmybxKE1dZUzOozAFBgMr\n"
++ "ZXADQQCnP7Oqx1epGnFnO7TrTJwcUukXDEYsINve2GeUsi8HEIeKKlMcLZ2Cnaj7\n"
++ "5v9NGuWh3QJpmmSGpEemiv8dJc4A\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA2 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBYTCCAROgAwIBAgIUP7Nmof8H2F1LyDkjqlYIUpGdXE8wBQYDK2VwMB0xGzAZ\n"
++ "BgNVBAMMEkdudVRMUyB0ZXN0IElDQSAkaTAgFw0yNDAzMTIyMjUzMzlaGA85OTk5\n"
++ "MTIzMTIzNTk1OVowHTEbMBkGA1UEAwwSR251VExTIHRlc3QgSUNBICRpMCowBQYD\n"
++ "K2VwAyEAkW9Rod3CXAnha6nlaHkDbCOegq94lgmjqclA9sOIt3yjYzBhMA8GA1Ud\n"
++ "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQ2inEK4KH6ATft\n"
++ "mybxKE1dZUzOozAfBgNVHSMEGDAWgBRPq/CQlK/zuXkjZvTCibu+vejD+jAFBgMr\n"
++ "ZXADQQBU+A+uF0yrtO/yv9cRUdCoL3Y1NKM35INg8BQDnkv724cW9zk1x0q9Fuou\n"
++ "zvfSVb8S3vT8fF5ZDOxarQs6ZH0C\n"
++ "-----END CERTIFICATE-----\n",
++ /* ICA1 */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBXTCCAQ+gAwIBAgIUfUWP+AQHpdFTRKTf21mMzjaJsp0wBQYDK2VwMBkxFzAV\n"
++ "BgNVBAMTDkdudVRMUyB0ZXN0IENBMCAXDTI0MDMxMjIyNTMzOVoYDzk5OTkxMjMx\n"
++ "MjM1OTU5WjAdMRswGQYDVQQDDBJHbnVUTFMgdGVzdCBJQ0EgJGkwKjAFBgMrZXAD\n"
++ "IQAVmfBAvLbT+pTD24pQrr6S0jEIFIV/qOv93yYvAUzpzKNjMGEwDwYDVR0TAQH/\n"
++ "BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0OBBYEFE+r8JCUr/O5eSNm9MKJ\n"
++ "u7696MP6MB8GA1UdIwQYMBaAFAFpt5wrFsqCtHc4PpluPDvwcxQLMAUGAytlcANB\n"
++ "AC6+XZnthjlUD0TbBKRF3qT5if3Pp29Bgvutw8859unzUZW8FkHg5KeDBj9ncgJc\n"
++ "O2tFnNH2hV6LDPJzU0rtLQc=\n"
++ "-----END CERTIFICATE-----\n",
++ NULL
++};
++
++static const char *many_icas_ca[] = {
++ /* CA (self-signed) */
++ "-----BEGIN CERTIFICATE-----\n"
++ "MIIBNzCB6qADAgECAhRjaokcQwcrtW8tjuVFz3A33F8POjAFBgMrZXAwGTEXMBUG\n"
++ "A1UEAxMOR251VExTIHRlc3QgQ0EwIBcNMjQwMzEyMjI1MzM5WhgPOTk5OTEyMzEy\n"
++ "MzU5NTlaMBkxFzAVBgNVBAMTDkdudVRMUyB0ZXN0IENBMCowBQYDK2VwAyEAvoxP\n"
++ "TNdbWktxA8qQNNH+25Cx9rzP+DxLGeI/7ODwrQGjQjBAMA8GA1UdEwEB/wQFMAMB\n"
++ "Af8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBQBabecKxbKgrR3OD6Zbjw78HMU\n"
++ "CzAFBgMrZXADQQCP5IUD74M7WrUx20uqzrzuj+s2jnBVmLQfWf/Ucetx+oTRFeq4\n"
++ "xZB/adWhycSeJUAB1zKqYUV9hgT8FWHbnHII\n"
++ "-----END CERTIFICATE-----\n",
++ NULL
++};
++
+ #if defined __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+ # pragma GCC diagnostic push
+ # pragma GCC diagnostic ignored "-Wunused-variable"
+@@ -4567,6 +4774,8 @@ static struct
+ GNUTLS_CERT_INSECURE_ALGORITHM | GNUTLS_CERT_INVALID, NULL, 1620118136, 1},
+ { "cross signed - ok", cross_signed, cross_signed_ca, 0, 0, 0,
+ 1704955300 },
++ { "many intermediates - ok", many_icas, many_icas_ca, 0, 0, 0,
++ 1710284400 },
+ { NULL, NULL, NULL, 0, 0}
+ };
+
+--
+2.40.0
diff --git a/meta/recipes-support/gnutls/gnutls_3.7.4.bb b/meta/recipes-support/gnutls/gnutls_3.7.4.bb
index b290022781..9f502e3f7c 100644
--- a/meta/recipes-support/gnutls/gnutls_3.7.4.bb
+++ b/meta/recipes-support/gnutls/gnutls_3.7.4.bb
@@ -26,6 +26,8 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar
file://CVE-2023-5981.patch \
file://CVE-2024-0553.patch \
file://CVE-2024-0567.patch \
+ file://CVE-2024-28834.patch \
+ file://CVE-2024-28835.patch \
"
SRC_URI[sha256sum] = "e6adbebcfbc95867de01060d93c789938cf89cc1d1f6ef9ef661890f6217451f"
diff --git a/meta/recipes-support/libssh2/libssh2/CVE-2023-48795.patch b/meta/recipes-support/libssh2/libssh2/CVE-2023-48795.patch
new file mode 100644
index 0000000000..c7a228217f
--- /dev/null
+++ b/meta/recipes-support/libssh2/libssh2/CVE-2023-48795.patch
@@ -0,0 +1,459 @@
+From d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a Mon Sep 17 00:00:00 2001
+From: Michael Buckley <michael@buckleyisms.com>
+Date: Thu, 30 Nov 2023 15:08:02 -0800
+Subject: [PATCH] src: add 'strict KEX' to fix CVE-2023-48795 "Terrapin Attack"
+
+Refs:
+https://terrapin-attack.com/ https://seclists.org/oss-sec/2023/q4/292
+https://osv.dev/list?ecosystem=&q=CVE-2023-48795 GHSA-45x7-px36-x8w8
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795
+
+Fixes #1290
+Closes #1291
+
+CVE: CVE-2023-48795
+Upstream-Status: Backport [https://github.com/libssh2/libssh2/commit/d34d9258b8420b19ec3f97b4cc5bf7aa7d98e35a]
+
+Signed-off-by: Meenali Gupta <meenali.gupta@windriver.com>
+---
+ src/kex.c | 64 +++++++++++++++++++++-------------
+ src/libssh2_priv.h | 18 +++++++---
+ src/packet.c | 85 +++++++++++++++++++++++++++++++++++++++++++---
+ src/packet.h | 2 +-
+ src/session.c | 3 ++
+ src/transport.c | 12 ++++++-
+ 6 files changed, 150 insertions(+), 34 deletions(-)
+
+diff --git a/src/kex.c b/src/kex.c
+index 9f3ef79..e040dcd 100644
+--- a/src/kex.c
++++ b/src/kex.c
+@@ -3026,6 +3026,13 @@ kex_method_ssh_curve25519_sha256 = {
+ };
+ #endif
+
++static const LIBSSH2_KEX_METHOD
++kex_method_strict_client_extension = {
++ "kex-strict-c-v00@openssh.com",
++ NULL,
++ 0,
++};
++
+ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
+ #if LIBSSH2_ED25519
+ &kex_method_ssh_curve25519_sha256,
+@@ -3043,6 +3050,7 @@ static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
+ &kex_method_diffie_helman_group14_sha1,
+ &kex_method_diffie_helman_group1_sha1,
+ &kex_method_diffie_helman_group_exchange_sha1,
++ &kex_method_strict_client_extension,
+ NULL
+ };
+
+@@ -3281,13 +3289,13 @@ static int kexinit(LIBSSH2_SESSION * session)
+ return 0;
+ }
+
+-/* kex_agree_instr
++/* _libssh2_kex_agree_instr
+ * Kex specific variant of strstr()
+ * Needle must be precede by BOL or ',', and followed by ',' or EOL
+ */
+-static unsigned char *
+-kex_agree_instr(unsigned char *haystack, unsigned long haystack_len,
+- const unsigned char *needle, unsigned long needle_len)
++unsigned char *
++_libssh2_kex_agree_instr(unsigned char *haystack, size_t haystack_len,
++ const unsigned char *needle, size_t needle_len)
+ {
+ unsigned char *s;
+ unsigned char *end_haystack;
+@@ -3371,7 +3379,7 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
+ while(s && *s) {
+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+ size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+- if(kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
++ if(_libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
+ const LIBSSH2_HOSTKEY_METHOD *method =
+ (const LIBSSH2_HOSTKEY_METHOD *)
+ kex_get_method_by_name((char *) s, method_len,
+@@ -3405,9 +3413,9 @@ static int kex_agree_hostkey(LIBSSH2_SESSION * session,
+ }
+
+ while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
+- s = kex_agree_instr(hostkey, hostkey_len,
+- (unsigned char *) (*hostkeyp)->name,
+- strlen((*hostkeyp)->name));
++ s = _libssh2_kex_agree_instr(hostkey, hostkey_len,
++ (unsigned char *) (*hostkeyp)->name,
++ strlen((*hostkeyp)->name));
+ if(s) {
+ /* So far so good, but does it suit our purposes? (Encrypting vs
+ Signing) */
+@@ -3442,13 +3450,19 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
+ const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
+ unsigned char *s;
+
++ const unsigned char *strict =
++ (unsigned char *)"kex-strict-s-v00@openssh.com";
++
++ if(_libssh2_kex_agree_instr(kex, kex_len, strict, 28)) {
++ session->kex_strict = 1;
++ }
+ if(session->kex_prefs) {
+ s = (unsigned char *) session->kex_prefs;
+
+ while(s && *s) {
+ unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
+ size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+- q = kex_agree_instr(kex, kex_len, s, method_len);
++ q = _libssh2_kex_agree_instr(kex, kex_len, s, method_len);
+ if(q) {
+ const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
+ kex_get_method_by_name((char *) s, method_len,
+@@ -3482,9 +3496,9 @@ static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
+ }
+
+ while(*kexp && (*kexp)->name) {
+- s = kex_agree_instr(kex, kex_len,
+- (unsigned char *) (*kexp)->name,
+- strlen((*kexp)->name));
++ s = _libssh2_kex_agree_instr(kex, kex_len,
++ (unsigned char *) (*kexp)->name,
++ strlen((*kexp)->name));
+ if(s) {
+ /* We've agreed on a key exchange method,
+ * Can we agree on a hostkey that works with this kex?
+@@ -3528,7 +3542,7 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+ size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+- if(kex_agree_instr(crypt, crypt_len, s, method_len)) {
++ if(_libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
+ const LIBSSH2_CRYPT_METHOD *method =
+ (const LIBSSH2_CRYPT_METHOD *)
+ kex_get_method_by_name((char *) s, method_len,
+@@ -3550,9 +3564,9 @@ static int kex_agree_crypt(LIBSSH2_SESSION * session,
+ }
+
+ while(*cryptp && (*cryptp)->name) {
+- s = kex_agree_instr(crypt, crypt_len,
+- (unsigned char *) (*cryptp)->name,
+- strlen((*cryptp)->name));
++ s = _libssh2_kex_agree_instr(crypt, crypt_len,
++ (unsigned char *) (*cryptp)->name,
++ strlen((*cryptp)->name));
+ if(s) {
+ endpoint->crypt = *cryptp;
+ return 0;
+@@ -3583,7 +3597,7 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+ size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+- if(kex_agree_instr(mac, mac_len, s, method_len)) {
++ if(_libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
+ const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
+ kex_get_method_by_name((char *) s, method_len,
+ (const LIBSSH2_COMMON_METHOD **)
+@@ -3604,8 +3618,9 @@ static int kex_agree_mac(LIBSSH2_SESSION * session,
+ }
+
+ while(*macp && (*macp)->name) {
+- s = kex_agree_instr(mac, mac_len, (unsigned char *) (*macp)->name,
+- strlen((*macp)->name));
++ s = _libssh2_kex_agree_instr(mac, mac_len,
++ (unsigned char *) (*macp)->name,
++ strlen((*macp)->name));
+ if(s) {
+ endpoint->mac = *macp;
+ return 0;
+@@ -3636,7 +3651,7 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
+ unsigned char *p = (unsigned char *) strchr((char *) s, ',');
+ size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
+
+- if(kex_agree_instr(comp, comp_len, s, method_len)) {
++ if(_libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
+ const LIBSSH2_COMP_METHOD *method =
+ (const LIBSSH2_COMP_METHOD *)
+ kex_get_method_by_name((char *) s, method_len,
+@@ -3658,8 +3673,9 @@ static int kex_agree_comp(LIBSSH2_SESSION *session,
+ }
+
+ while(*compp && (*compp)->name) {
+- s = kex_agree_instr(comp, comp_len, (unsigned char *) (*compp)->name,
+- strlen((*compp)->name));
++ s = _libssh2_kex_agree_instr(comp, comp_len,
++ (unsigned char *) (*compp)->name,
++ strlen((*compp)->name));
+ if(s) {
+ endpoint->comp = *compp;
+ return 0;
+@@ -3856,7 +3872,8 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
+ session->local.kexinit = key_state->oldlocal;
+ session->local.kexinit_len = key_state->oldlocal_len;
+ key_state->state = libssh2_NB_state_idle;
+- session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
++ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
++ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+ return -1;
+ }
+@@ -3904,6 +3921,7 @@ _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
+ session->remote.kexinit = NULL;
+ }
+
++ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
+ session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+
+diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
+index da488b7..7faeab6 100644
+--- a/src/libssh2_priv.h
++++ b/src/libssh2_priv.h
+@@ -640,6 +640,9 @@ struct _LIBSSH2_SESSION
+ unsigned char server_hostkey_sha256[SHA256_DIGEST_LENGTH];
+ int server_hostkey_sha256_valid;
+
++ /* Whether to use the OpenSSH Strict KEX extension */
++ int kex_strict;
++
+ /* (remote as source of data -- packet_read ) */
+ libssh2_endpoint_data remote;
+
+@@ -809,6 +812,7 @@ struct _LIBSSH2_SESSION
+ int fullpacket_macstate;
+ size_t fullpacket_payload_len;
+ int fullpacket_packet_type;
++ uint32_t fullpacket_required_type;
+
+ /* State variables used in libssh2_sftp_init() */
+ libssh2_nonblocking_states sftpInit_state;
+@@ -856,10 +860,11 @@ struct _LIBSSH2_SESSION
+ };
+
+ /* session.state bits */
+-#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000001
+-#define LIBSSH2_STATE_NEWKEYS 0x00000002
+-#define LIBSSH2_STATE_AUTHENTICATED 0x00000004
+-#define LIBSSH2_STATE_KEX_ACTIVE 0x00000008
++#define LIBSSH2_STATE_INITIAL_KEX 0x00000001
++#define LIBSSH2_STATE_EXCHANGING_KEYS 0x00000002
++#define LIBSSH2_STATE_NEWKEYS 0x00000004
++#define LIBSSH2_STATE_AUTHENTICATED 0x00000008
++#define LIBSSH2_STATE_KEX_ACTIVE 0x00000010
+
+ /* session.flag helpers */
+ #ifdef MSG_NOSIGNAL
+@@ -1076,6 +1081,11 @@ ssize_t _libssh2_send(libssh2_socket_t socket, const void *buffer,
+ int _libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
+ key_exchange_state_t * state);
+
++unsigned char *_libssh2_kex_agree_instr(unsigned char *haystack,
++ size_t haystack_len,
++ const unsigned char *needle,
++ size_t needle_len);
++
+ /* Let crypt.c/hostkey.c expose their method structs */
+ const LIBSSH2_CRYPT_METHOD **libssh2_crypt_methods(void);
+ const LIBSSH2_HOSTKEY_METHOD **libssh2_hostkey_methods(void);
+diff --git a/src/packet.c b/src/packet.c
+index 04937d6..786ba40 100644
+--- a/src/packet.c
++++ b/src/packet.c
+@@ -467,14 +467,13 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
+ * layer when it has received a packet.
+ *
+ * The input pointer 'data' is pointing to allocated data that this function
+- * is asked to deal with so on failure OR success, it must be freed fine.
+- * The only exception is when the return code is LIBSSH2_ERROR_EAGAIN.
++ * will be freed unless return the code is LIBSSH2_ERROR_EAGAIN.
+ *
+ * This function will always be called with 'datalen' greater than zero.
+ */
+ int
+ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
+- size_t datalen, int macstate)
++ size_t datalen, int macstate, uint32_t seq)
+ {
+ int rc = 0;
+ unsigned char *message = NULL;
+@@ -517,6 +516,70 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
+ break;
+ }
+
++ if(session->state & LIBSSH2_STATE_INITIAL_KEX) {
++ if(msg == SSH_MSG_KEXINIT) {
++ if(!session->kex_strict) {
++ if(datalen < 17) {
++ LIBSSH2_FREE(session, data);
++ session->packAdd_state = libssh2_NB_state_idle;
++ return _libssh2_error(session,
++ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
++ "Data too short extracting kex");
++ }
++ else {
++ const unsigned char *strict =
++ (unsigned char *)"kex-strict-s-v00@openssh.com";
++ struct string_buf buf;
++ unsigned char *algs = NULL;
++ size_t algs_len = 0;
++
++ buf.data = (unsigned char *)data;
++ buf.dataptr = buf.data;
++ buf.len = datalen;
++ buf.dataptr += 17; /* advance past type and cookie */
++
++ if(_libssh2_get_string(&buf, &algs, &algs_len)) {
++ LIBSSH2_FREE(session, data);
++ session->packAdd_state = libssh2_NB_state_idle;
++ return _libssh2_error(session,
++ LIBSSH2_ERROR_BUFFER_TOO_SMALL,
++ "Algs too short");
++ }
++
++ if(algs_len == 0 ||
++ _libssh2_kex_agree_instr(algs, algs_len, strict, 28)) {
++ session->kex_strict = 1;
++ }
++ }
++ }
++
++ if(session->kex_strict && seq) {
++ LIBSSH2_FREE(session, data);
++ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
++ session->packAdd_state = libssh2_NB_state_idle;
++ libssh2_session_disconnect(session, "strict KEX violation: "
++ "KEXINIT was not the first packet");
++
++ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
++ "strict KEX violation: "
++ "KEXINIT was not the first packet");
++ }
++ }
++
++ if(session->kex_strict && session->fullpacket_required_type &&
++ session->fullpacket_required_type != msg) {
++ LIBSSH2_FREE(session, data);
++ session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
++ session->packAdd_state = libssh2_NB_state_idle;
++ libssh2_session_disconnect(session, "strict KEX violation: "
++ "unexpected packet type");
++
++ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
++ "strict KEX violation: "
++ "unexpected packet type");
++ }
++ }
++
+ if(session->packAdd_state == libssh2_NB_state_allocated) {
+ /* A couple exceptions to the packet adding rule: */
+ switch(msg) {
+@@ -1118,7 +1181,16 @@ _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
+
+ return 0;
+ }
+- packet = _libssh2_list_next(&packet->node);
++ else if(session->kex_strict &&
++ (session->state & LIBSSH2_STATE_INITIAL_KEX)) {
++ libssh2_session_disconnect(session, "strict KEX violation: "
++ "unexpected packet type");
++
++ return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
++ "strict KEX violation: "
++ "unexpected packet type");
++ }
++ packet = _libssh2_list_next(&packet->node);
+ }
+ return -1;
+ }
+@@ -1179,7 +1251,10 @@ _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
+ }
+
+ while(session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
+- int ret = _libssh2_transport_read(session);
++ int ret;
++ session->fullpacket_required_type = packet_type;
++ ret = _libssh2_transport_read(session);
++ session->fullpacket_required_type = 0;
+ if(ret == LIBSSH2_ERROR_EAGAIN)
+ return ret;
+ else if(ret < 0) {
+diff --git a/src/packet.h b/src/packet.h
+index 79018bc..08ea2a2 100644
+--- a/src/packet.h
++++ b/src/packet.h
+@@ -71,6 +71,6 @@ int _libssh2_packet_burn(LIBSSH2_SESSION * session,
+ int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
+ unsigned long data_len);
+ int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
+- size_t datalen, int macstate);
++ size_t datalen, int macstate, uint32_t seq);
+
+ #endif /* __LIBSSH2_PACKET_H */
+diff --git a/src/session.c b/src/session.c
+index 212560b..019b9ed 100644
+--- a/src/session.c
++++ b/src/session.c
+@@ -500,6 +500,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
+ session->abstract = abstract;
+ session->api_timeout = 0; /* timeout-free API by default */
+ session->api_block_mode = 1; /* blocking API by default */
++ session->state = LIBSSH2_STATE_INITIAL_KEX;
++ session->fullpacket_required_type = 0;
+ _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
+ "New session resource allocated");
+ _libssh2_init_if_needed();
+@@ -1171,6 +1173,7 @@ libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
+ const char *desc, const char *lang)
+ {
+ int rc;
++ session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
+ session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
+ BLOCK_ADJUST(rc, session,
+ session_disconnect(session, reason, desc, lang));
+diff --git a/src/transport.c b/src/transport.c
+index 1074fc2..6823b63 100644
+--- a/src/transport.c
++++ b/src/transport.c
+@@ -168,6 +168,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
+ struct transportpacket *p = &session->packet;
+ int rc;
+ int compressed;
++ uint32_t seq = session->remote.seqno;
+
+ if(session->fullpacket_state == libssh2_NB_state_idle) {
+ session->fullpacket_macstate = LIBSSH2_MAC_CONFIRMED;
+@@ -240,7 +241,7 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
+ if(session->fullpacket_state == libssh2_NB_state_created) {
+ rc = _libssh2_packet_add(session, p->payload,
+ session->fullpacket_payload_len,
+- session->fullpacket_macstate);
++ session->fullpacket_macstate, seq);
+ if(rc == LIBSSH2_ERROR_EAGAIN)
+ return rc;
+ if(rc) {
+@@ -251,6 +252,11 @@ fullpacket(LIBSSH2_SESSION * session, int encrypted /* 1 or 0 */ )
+
+ session->fullpacket_state = libssh2_NB_state_idle;
+
++ if(session->kex_strict &&
++ session->fullpacket_packet_type == SSH_MSG_NEWKEYS) {
++ session->remote.seqno = 0;
++ }
++
+ return session->fullpacket_packet_type;
+ }
+
+@@ -892,6 +898,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
+
+ session->local.seqno++;
+
++ if(session->kex_strict && data[0] == SSH_MSG_NEWKEYS) {
++ session->local.seqno = 0;
++ }
++
+ ret = LIBSSH2_SEND(session, p->outbuf, total_length,
+ LIBSSH2_SOCKET_SEND_FLAGS(session));
+ if(ret < 0)
+--
+2.40.0
diff --git a/meta/recipes-support/libssh2/libssh2_1.10.0.bb b/meta/recipes-support/libssh2/libssh2_1.10.0.bb
index 8483a292c2..8fd77996d5 100644
--- a/meta/recipes-support/libssh2/libssh2_1.10.0.bb
+++ b/meta/recipes-support/libssh2/libssh2_1.10.0.bb
@@ -11,6 +11,7 @@ SRC_URI = "http://www.libssh2.org/download/${BP}.tar.gz \
file://fix-ssh2-test.patch \
file://run-ptest \
file://CVE-2020-22218.patch \
+ file://CVE-2023-48795.patch \
"
SRC_URI[sha256sum] = "2d64e90f3ded394b91d3a2e774ca203a4179f69aebee03003e5a6fa621e41d51"
diff --git a/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0001.patch b/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0001.patch
new file mode 100644
index 0000000000..e1d909b0d1
--- /dev/null
+++ b/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0001.patch
@@ -0,0 +1,110 @@
+From 00201ecd8f982da3b67d4f6868af72a1b03b14e0 Mon Sep 17 00:00:00 2001
+From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
+Date: Sat, 9 Mar 2024 16:26:42 +0900
+Subject: [PATCH] Limit CONTINUATION frames following an incoming HEADER frame
+
+CVE: CVE-2024-28182
+
+Upstream-Status: Backport [https://github.com/nghttp2/nghttp2/commit/00201ecd8f982da3b67d4f6868af72a1b03b14e0]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ lib/includes/nghttp2/nghttp2.h | 7 ++++++-
+ lib/nghttp2_helper.c | 2 ++
+ lib/nghttp2_session.c | 7 +++++++
+ lib/nghttp2_session.h | 10 ++++++++++
+ 4 files changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h
+index 2bd35f4..6cc8c0c 100644
+--- a/lib/includes/nghttp2/nghttp2.h
++++ b/lib/includes/nghttp2/nghttp2.h
+@@ -440,7 +440,12 @@ typedef enum {
+ * exhaustion on server side to send these frames forever and does
+ * not read network.
+ */
+- NGHTTP2_ERR_FLOODED = -904
++ NGHTTP2_ERR_FLOODED = -904,
++ /**
++ * When a local endpoint receives too many CONTINUATION frames
++ * following a HEADER frame.
++ */
++ NGHTTP2_ERR_TOO_MANY_CONTINUATIONS = -905,
+ } nghttp2_error;
+
+ /**
+diff --git a/lib/nghttp2_helper.c b/lib/nghttp2_helper.c
+index 588e269..98989f6 100644
+--- a/lib/nghttp2_helper.c
++++ b/lib/nghttp2_helper.c
+@@ -336,6 +336,8 @@ const char *nghttp2_strerror(int error_code) {
+ "closed";
+ case NGHTTP2_ERR_TOO_MANY_SETTINGS:
+ return "SETTINGS frame contained more than the maximum allowed entries";
++ case NGHTTP2_ERR_TOO_MANY_CONTINUATIONS:
++ return "Too many CONTINUATION frames following a HEADER frame";
+ default:
+ return "Unknown error code";
+ }
+diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c
+index 5c834fa..537127c 100644
+--- a/lib/nghttp2_session.c
++++ b/lib/nghttp2_session.c
+@@ -464,6 +464,7 @@ static int session_new(nghttp2_session **session_ptr,
+ (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
+ (*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
+ (*session_ptr)->max_settings = NGHTTP2_DEFAULT_MAX_SETTINGS;
++ (*session_ptr)->max_continuations = NGHTTP2_DEFAULT_MAX_CONTINUATIONS;
+
+ if (option) {
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
+@@ -6307,6 +6308,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
+ }
+ }
+ session_inbound_frame_reset(session);
++
++ session->num_continuations = 0;
+ }
+ break;
+ }
+@@ -6428,6 +6431,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
+ }
+ #endif /* DEBUGBUILD */
+
++ if (++session->num_continuations > session->max_continuations) {
++ return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS;
++ }
++
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+
+diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h
+index 5f71a16..9a00b0e 100644
+--- a/lib/nghttp2_session.h
++++ b/lib/nghttp2_session.h
+@@ -107,6 +107,10 @@ typedef struct {
+ #define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
+ #define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
+
++/* The default max number of CONTINUATION frames following an incoming
++ HEADER frame. */
++#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
++
+ /* Internal state when receiving incoming frame */
+ typedef enum {
+ /* Receiving frame header */
+@@ -279,6 +283,12 @@ struct nghttp2_session {
+ size_t max_send_header_block_length;
+ /* The maximum number of settings accepted per SETTINGS frame. */
+ size_t max_settings;
++ /* The maximum number of CONTINUATION frames following an incoming
++ HEADER frame. */
++ size_t max_continuations;
++ /* The number of CONTINUATION frames following an incoming HEADER
++ frame. This variable is reset when END_HEADERS flag is seen. */
++ size_t num_continuations;
+ /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
+ uint32_t next_stream_id;
+ /* The last stream ID this session initiated. For client session,
+--
+2.40.0
diff --git a/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0002.patch b/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0002.patch
new file mode 100644
index 0000000000..fee19465d5
--- /dev/null
+++ b/meta/recipes-support/nghttp2/nghttp2/CVE-2024-28182-0002.patch
@@ -0,0 +1,105 @@
+From d71a4668c6bead55805d18810d633fbb98315af9 Mon Sep 17 00:00:00 2001
+From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
+Date: Sat, 9 Mar 2024 16:48:10 +0900
+Subject: [PATCH] Add nghttp2_option_set_max_continuations
+
+CVE: CVE-2024-28182
+
+Upstream-Status: Backport [https://github.com/nghttp2/nghttp2/commit/d71a4668c6bead55805d18810d633fbb98315af9]
+
+Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
+---
+ doc/Makefile.am | 1 +
+ lib/includes/nghttp2/nghttp2.h | 11 +++++++++++
+ lib/nghttp2_option.c | 5 +++++
+ lib/nghttp2_option.h | 5 +++++
+ lib/nghttp2_session.c | 4 ++++
+ 5 files changed, 26 insertions(+)
+
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index b9d5a2d..83cfdfd 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -70,6 +70,7 @@ APIDOCS= \
+ nghttp2_option_set_no_recv_client_magic.rst \
+ nghttp2_option_set_peer_max_concurrent_streams.rst \
+ nghttp2_option_set_user_recv_extension_type.rst \
++ nghttp2_option_set_max_continuations.rst \
+ nghttp2_option_set_max_outbound_ack.rst \
+ nghttp2_option_set_max_settings.rst \
+ nghttp2_option_set_stream_reset_rate_limit.rst \
+diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h
+index 6cc8c0c..c77cca9 100644
+--- a/lib/includes/nghttp2/nghttp2.h
++++ b/lib/includes/nghttp2/nghttp2.h
+@@ -2724,6 +2724,17 @@ NGHTTP2_EXTERN void nghttp2_option_set_max_outbound_ack(nghttp2_option *option,
+ NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
+ size_t val);
+
++/**
++ * @function
++ *
++ * This function sets the maximum number of CONTINUATION frames
++ * following an incoming HEADER frame. If more than those frames are
++ * received, the remote endpoint is considered to be misbehaving and
++ * session will be closed. The default value is 8.
++ */
++NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option,
++ size_t val);
++
+ /**
+ * @function
+ *
+diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c
+index 0d9a404..f3659c1 100644
+--- a/lib/nghttp2_option.c
++++ b/lib/nghttp2_option.c
+@@ -133,3 +133,8 @@ void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
+ option->stream_reset_burst = burst;
+ option->stream_reset_rate = rate;
+ }
++
++void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
++ option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
++ option->max_continuations = val;
++}
+diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h
+index e6ba910..c1b48c7 100644
+--- a/lib/nghttp2_option.h
++++ b/lib/nghttp2_option.h
+@@ -69,6 +69,7 @@ typedef enum {
+ NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
+ NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
+ NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
++ NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
+ } nghttp2_option_flag;
+
+ /**
+@@ -96,6 +97,10 @@ struct nghttp2_option {
+ * NGHTTP2_OPT_MAX_SETTINGS
+ */
+ size_t max_settings;
++ /**
++ * NGHTTP2_OPT_MAX_CONTINUATIONS
++ */
++ size_t max_continuations;
+ /**
+ * Bitwise OR of nghttp2_option_flag to determine that which fields
+ * are specified.
+diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c
+index 537127c..b390cd5 100644
+--- a/lib/nghttp2_session.c
++++ b/lib/nghttp2_session.c
+@@ -539,6 +539,10 @@ static int session_new(nghttp2_session **session_ptr,
+ option->stream_reset_burst,
+ option->stream_reset_rate);
+ }
++
++ if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) {
++ (*session_ptr)->max_continuations = option->max_continuations;
++ }
+ }
+
+ rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
+--
+2.40.0
diff --git a/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb b/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
index b67313b5c2..79b1cf95c5 100644
--- a/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
+++ b/meta/recipes-support/nghttp2/nghttp2_1.47.0.bb
@@ -11,6 +11,8 @@ SRC_URI = "\
file://0001-fetch-ocsp-response-use-python3.patch \
file://CVE-2023-35945.patch \
file://CVE-2023-44487.patch \
+ file://CVE-2024-28182-0001.patch \
+ file://CVE-2024-28182-0002.patch \
"
SRC_URI[sha256sum] = "68271951324554c34501b85190f22f2221056db69f493afc3bbac8e7be21e7cc"